3 / 3 / 0
Регистрация: 11.10.2012
Сообщений: 88
1

Тест Миллера-Рабина

18.02.2014, 18:31. Показов 17061. Ответов 16
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день всем. Алгоритм для теста взял с википедии. Вот он:
Кликните здесь для просмотра всего текста

Ввод: m > 2, нечётное натуральное число, которое необходимо проверить на простоту;
r — количество раундов.
Вывод: составное, означает, что m является составным числом;
вероятно простое, означает, что m с высокой вероятностью является простым числом.
Представить m − 1 в виде 2s·t, где t нечётно, можно сделать последовательным делением m - 1 на 2.
цикл А: повторить r раз:
Выбрать случайное целое число a в отрезке [2, m − 2]
x ← at mod m, вычисляется с помощью алгоритма возведения в степень по модулю (англ.)
если x = 1 или x = m − 1, то перейти на следующую итерацию цикла А
цикл B: повторить s − 1 раз
x ← x2 mod m
если x = 1, то вернуть составное
если x = m − 1, то перейти на следующую итерацию цикла A
вернуть составное
вернуть вероятно простое


Набросал простенькую программку, но она возвращает неправильные ответы! Если есть идеи - подскажите, пожалуйста в чем ошибка.
З.Ы. За код сильно не ругайте, я учусь)
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
 private void button_go_Click(object sender, EventArgs e)
        {
            int m = Convert.ToInt32(textBox_number.Text); //Число
            int r = Convert.ToInt32(textBox_rounds.Text); //Количество раундов
            if (miller_rabin(m, r)) textBox_result.Text = "Число простое!";
            else textBox_result.Text = "Число составное!";
        }
 
        public bool miller_rabin(int m, int r) //false - составное, true - простое
        {
            int s = 0, t = m - 1; Random rand = new Random();
            //Каноническое разложение числа m = 2^s*t
            while (true)
            {
                t = t / 2; s++;
                if (prost(t)) break;
            }
            //
            //Цикл А
            //
            for (int i = 0; i < r; i++)
            {
                int a = rand.Next(2, m - 2);
                int x = step(a, t, m);
                if (x != 1 || x != m - 1)  //Цикл B
                {
                    for (int j = 0; j < s - 1; j++)
                    {
                        x = step(x, 2, m);
                        if (x == 1) return false;
                        if (x == m - 1) break;
                    }
                    return false;
                }
            }
            return true;
        }
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.02.2014, 18:31
Ответы с готовыми решениями:

тест миллера-рабина, pascal -> c++
собсно, кто знает дельфи и с++, обьясните где я не прав пожалуйста=) дельфи: {IsPrime.Pas ver....

Тест Миллера-Рабина. Как получить число t из формулы
Что то я никак не могу понять как получить число t из формулы m-1={2}^{s}*t. Делаю по алгоритму...

алгоритм Миллера-Рабина проверки простоты многоразрядных чисел.
надо составить алгоритм Миллера-Рабина проверки простоты многоразрядных чисел. Я составил, ...

Реализация теста Рабина-Миллера для чисел порядка 2^512
Необходимо реализовать тест для таких вот БОЛЬШИХ чисел. Но с арифметикой больших чисел на C\C++ не...

16
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
18.02.2014, 20:22 2
C#
1
if (prost(t))
а что за метод prost?
0
3 / 3 / 0
Регистрация: 11.10.2012
Сообщений: 88
19.02.2014, 12:26  [ТС] 3
Это примитивный метод проверки чисел на простоту
C#
1
2
3
4
5
6
7
8
public bool prost(int a) 
        {
            for (int i = 2; i < a / 2 + 1; i++)
            {
                if (a % i == 0) return false;
            }
            return true;
        }
Так же есть функция, которую я не написал - это возведение в степень по модулю

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public int step(int a, int b, int mod) // Нахожддение числа по модулю
        {
            int res = 1;
            for (int i = b; i > 0; i--)
            {
                res = res * a;
                if (res > mod)
                {
                    res = res % mod;
                }
            }
            /*if (res - mod == -1)
            {
                return -1;
            }*/
            return res;
        }
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
19.02.2014, 12:54 4
OdessaTV, а смысл тогда в этом методе, если он использует примитивный перебор?

Добавлено через 53 секунды
Тогда уж сразу:
C#
1
2
3
4
 public bool miller_rabin(int m, int r)
{
   return prost(m);
}
0
3 / 3 / 0
Регистрация: 11.10.2012
Сообщений: 88
19.02.2014, 12:59  [ТС] 5
Мне нужно разложить число m -1 в виде 2^s*t (это написано в алгоритме на Вики) я не придумал лучшего способа. А проверку на простоту мне нужно сделать именно рандомизированным тестом Миллера-Рабина. Такие вот дела..
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
19.02.2014, 14:13 6
OdessaTV, я пытаюсь вам объяснить, что вы написали неправильно. В википедии не написано "делить, пока число не станет простым", иначе я уже говорил, смысл писать такой большой алгоритм когда можно обойтись одной строчкой...

Добавлено через 21 минуту
OdessaTV, вот, набросал примерный правильный вариант, брал с английской вики, т.к. в русской некоторые важные детали опущены почему-то (например, что алгоритм работает только для нечетных чисел, поэтому нужно дописать третье условие в 7 строчке). Так что держите описание на английском и практически дословную реализацию на шарпе:
http://en.wikipedia.org/wiki/M... nning_time
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test#Algorithm_and_running_time
        static bool MillerRabinTest(int n, int k)
        {
            if (n <= 1)
                return false;
            if (n == 2)
                return true;
            if (n%2 == 0)
                return false;
            int s = 0, d = n - 1;
            while (d%2 == 0)
            {
                d /= 2;
                s++;
            }
 
            var rand = new Random();
 
            for (int i = 0; i < k; i++)
            {
                long a = rand.Next(2, n - 1);
                int x = (int) BigInteger.ModPow(a, d, n);
                if (x == 1 || x == n - 1)
                    continue;
                for (int j = 0; j < s - 1; j++)
                {
                    x = (x*x)%n;
                    if (x == 1)
                        return false;
                    if (x == n - 1)
                        break;
                }
                if (x != n-1)
                    return false;
            }
            return true;
        }
как видите, никаких IsPrime нет и быть не может.

Добавлено через 1 минуту
OdessaTV, BigInteger живет в нейспейсе System.Numerics, так что добавьте ссылочку. Ну или напишите свой алгоритм факторизации.
2
3 / 3 / 0
Регистрация: 11.10.2012
Сообщений: 88
19.02.2014, 14:47  [ТС] 7
Psilon, спасибо Вам огромное, с алгоритмом разобрался, все понятно как день, попытаюсь найти в чем же была у меня ошибка, в нескольких случаях просто изобретал велосипед... Спасибо большое еще раз.
Проверял для чисел 767761, 1650353, 1173521 - говорит, что составные... Наверное изъян самого алгоритма, а не реализации...
0
Эксперт Java
4091 / 3825 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 11
19.02.2014, 17:28 8
Цитата Сообщение от OdessaTV Посмотреть сообщение
Проверял для чисел 767761, 1650353, 1173521 - говорит, что составные... Наверное изъян самого алгоритма, а не реализации
Насколько я знаю, такого быть не может. Тест Рабина-Миллера не может сказать, что число составное, если оно не составное.
0
3 / 3 / 0
Регистрация: 11.10.2012
Сообщений: 88
20.02.2014, 13:38  [ТС] 9
Цитата Сообщение от turbanoff Посмотреть сообщение
Тест Рабина-Миллера не может сказать, что число составное, если оно не составное.
Запустите и проверьте, может я что-то неправильно сделал...
0
Эксперт Java
4091 / 3825 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 11
20.02.2014, 13:43 10
Цитата Сообщение от OdessaTV Посмотреть сообщение
Запустите и проверьте, может я что-то неправильно сделал...
Я к тому, что если тест выдает такое, то значит проблема именно в реализации.
0
3 / 3 / 0
Регистрация: 11.10.2012
Сообщений: 88
20.02.2014, 18:44  [ТС] 11
turbanoff, именно этот алгоритм написан на википедии, Psilon, написал все буквально слово в слово по алгоритму, выходит, что вики врет? К тому же это рандомизированный тест на простоту, по идее, на большом количестве раундов оно таки должно дать правильный ответ. Поправьте, если не прав.
0
Эксперт Java
4091 / 3825 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 11
20.02.2014, 20:10 12
Цитата Сообщение от OdessaTV Посмотреть сообщение
Psilon, написал все буквально слово в слово по алгоритму, выходит, что вики врет?
Вики не врёт. Врёт конкретная реализация. В коде Psilon есть баг с переполнением переменой x(при возведении в квадрат). Если объявить её как long - то всё будет работать, по крайней мере на приведённых вами числах.

Цитата Сообщение от OdessaTV Посмотреть сообщение
К тому же это рандомизированный тест на простоту, по идее, на большом количестве раундов оно таки должно дать правильный ответ. Поправьте, если не прав.
Вы не правы. Тест Рабина-Миллера НЕ может сказать что число составное, если оно таковым не является.
2
3 / 3 / 0
Регистрация: 11.10.2012
Сообщений: 88
21.02.2014, 14:56  [ТС] 13
Спасибо огромное за разъяснения. Мне это очень помогло.
0
1437 / 1014 / 228
Регистрация: 31.05.2013
Сообщений: 6,645
Записей в блоге: 6
28.12.2015, 05:09 14
Хоть уже больше года прошло, но всё же..
Цитата Сообщение от turbanoff Посмотреть сообщение
Тест Рабина-Миллера НЕ может сказать что число составное, если оно таковым не является.
__________________
На простые числа тест Миллера-Рабина реагирует исправно. Но попробуйте разобрать числа 561, 1105. Сам по себе алгоритм М.-Р. скажет, что они простые,хотя на самом деле это не так (см. числа Кармайкла).
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
03.01.2016, 20:17 15
Matan!, ну не знаю, возвращает Composite как и должен:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class Program
    {
        static void Main(string[] args)
        {
            int[] ints = {561, 1105, 31};
            foreach (int x in ints)
            {
                Console.WriteLine($"{x} - IsPrime: {MillerRabinTest(x, 10)}");
            }
        }
 
        //http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test#Algorithm_and_running_time
        public static bool MillerRabinTest(int n, int k)
        {
            if (n < 2)
                return false;
            if (n == 2)
                return true;
            if (n%2 == 0)
                return false;
            int r = 0, d = n - 1;
            while (d%2 == 0)
            {
                d /= 2;
                r++;
            }
 
            var rand = new Random();
 
            for (int i = 0; i < k; i++)
            {
                int a = rand.Next(2, n - 1);
                BigInteger x = BigInteger.ModPow(a, d, n);
                if (x == 1 || x == n - 1)
                    continue;
                for (int j = 0; j < r - 1; j++)
                {
                    x = BigInteger.ModPow(x, 2, n);
                    if (x == 1)
                        return false;
                    if (x == n - 1)
                        break;
                }
                if (x != n - 1)
                    return false;
            }
            return true;
        }
    }
0
nedel
03.01.2016, 20:43
  #16

Не по теме:

Цитата Сообщение от Psilon Посмотреть сообщение
Console.WriteLine($"{x} - IsPrime: {MillerRabinTest(x, 10)}");
что-то я упустил из новинок... Где можно почитать о использовании $ перед строкой?

0
Storm23
03.01.2016, 22:59     Тест Миллера-Рабина
  #17

Не по теме:

Цитата Сообщение от nedel Посмотреть сообщение
что-то я упустил из новинок... Где можно почитать о использовании $ перед строкой?
Это C#6 http://habrahabr.ru/post/249555/

0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
03.01.2016, 22:59

Индексы Миллера Кристаллография
Боже поясните за индексы Миллера.Человеческим языком расскажите пожалуйста что они делают и как...

Генератор псевдослучайных чисел Парка-Миллера
Здравствуйте! Как мне решить данную задачу? Минимальный генератор Парка- Миллера Простейшая...

Алгоритм Миллера и Мюллера (Mueller-Muller)
Здравствуйте. В описании алгоритма (например, здесь:...

методы борьбы с эффектом Миллера на mosfet
Привет. Столкнулся с проблемой измерение затухание ультразвукового сигнала в среде. При разных...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru