Эксперт С++
 Аватар для Thinker
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5

Быстрая проверка натурального числа на простоту

29.09.2012, 21:35. Показов 146699. Ответов 121
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Часто возникает задача проверки натурального числа на простоту. При этом имеются вероятностные и детерминированные методы проверки. Здесь рассматриваются только детерминированные алгоритмы, дающие 100% ответ на вопрос о простоте.

Хорошо известно такое утверждение: если натуральное число n>1 не делится ни на одно простое число, не превосходящее https://www.cyberforum.ru/cgi-bin/latex.cgi?\sqrt{n}, то оно простое. В связи с этим получается самый простой способ проверки на простоту алгоритм

C++
1
2
3
4
5
6
7
8
9
10
11
int Prime(unsigned long a)
{
   unsigned long i;
   if (a == 2)
      return 1;
   if (a == 0 || a == 1 || a % 2 == 0)
      return 0;
   for(i = 3; i*i <= a && a % i; i += 2)
      ;
   return i*i > a;
}
В данном алгоритме из множества https://www.cyberforum.ru/cgi-bin/latex.cgi?\{2,3,...,\sqrt{n}\} отброшено 50% четных чисел, так как если число a не делится на 2, то нет смыла делить его на 4, 6 и т.д. Данный метод можно усовершенствовать и отбросить из множества https://www.cyberforum.ru/cgi-bin/latex.cgi?\{2,3,...,\sqrt{n}\} больше чисел. Для этого выбирается некоторое число m, равное произведению простых чисел без степеней и рассматриваются только те элементы множества https://www.cyberforum.ru/cgi-bin/latex.cgi?\{2,3,...,\sqrt{n}\}, которые взаимно просты с m. Например, если m = 6 = 2*3, то из этого множества отбрасывается 66% элементов (ненужных проверок). В этом случае алгоритм будет быстрее предыдущего при больших n

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int Prime(unsigned long a)
{
   unsigned long i, j, bound;
   if (a == 0 || a == 1)
      return 0;
   if (a == 2 || a == 3 || a == 5)
      return 1;
   if (a%2 == 0 || a%3 == 0 || a%5 == 0)
      return 0;
   bound = sqrt((double)a);
   i = 7; j = 11;
   while (j <= bound && a%i && a%j)
   {
       i += 6; j += 6;
   }
   if (j <= bound || i <= bound && a%i == 0)
      return 0;
   return 1;
}
Если m = 30 = 2*3*5, то такой алгоритм будет еще быстрее и отбрасывает уже 74% лишних элементов

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
int Prime(unsigned long a)
{
   unsigned long i1, i2, i3, i4, i5, i6, i7, i8, bound;
   if (a == 0 || a == 1)
      return 0;
   if (a == 2 || a == 3 || a == 5 || a == 7 || a == 11 || a == 13 || a == 17 || a == 19 || a == 23 || a == 29)
      return 1;
   if (a%2 == 0 || a%3 == 0 || a%5 == 0 || a%7 == 0 || a%11 == 0 || a%13 == 0 || a%17 == 0 || a%19 == 0 || a%23 == 0 || a%29 == 0)
      return 0;
   bound = sqrt((double)a);
   i1 = 31; i2 = 37; i3 = 41; i4 = 43; i5 = 47; i6 = 49; i7 = 53; i8 = 59;
   while (i8 <= bound && a%i1 && a%i2 && a%i3 && a%i4 && a%i5 && a%i6 && a%i7 && a%i8)
   {
       i1 += 30; i2 += 30; i3 += 30; i4 += 30; i5 += 30; i6 += 30; i7 += 30; i8 += 30;
   }
   if (i8 <= bound ||
      i1 <= bound && a % i1 == 0 ||
      i2 <= bound && a % i2 == 0 ||
      i3 <= bound && a % i3 == 0 ||
      i4 <= bound && a % i4 == 0 ||
      i5 <= bound && a % i5 == 0 ||
      i6 <= bound && a % i6 == 0 ||
      i7 <= bound && a % i7 == 0)
         return 0;
   return 1;
}
Вот такие интересные наработки получились. У кого есть варианты, работающие быстрее, добавляйте.
33
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
29.09.2012, 21:35
Ответы с готовыми решениями:

Проверка на простоту числа
как мне сделать так, чтобы узнать простое является число или составное, не через bool, а как-нибудь через оператор switch case: т е, case...

Проверка числа на простоту
Помогите написать программу которая проверяет простое число или нет.

Проверка числа на простоту
Дано натуральное число n&gt;1. Проверьте, является ли оно простым. Программа должна вывести слово YES, если число простое и NO, если число...

121
24 / 3 / 0
Регистрация: 28.10.2012
Сообщений: 35
01.11.2012, 19:26
Студворк — интернет-сервис помощи студентам
ValeryS, да, я там потом решил этот вопрос, все дело было в этом операторе:
C++
1
ulong d = 1 << 35;
а надо было
C++
1
ulong d = (ulong)1 << 35;
Добавлено через 9 часов 24 минуты
Thinker, в общем написал алгоритм, может его стоит оптимизировать, потому что по скорости он проигрывает в 8 раз! и уже для 128 битных чисел нужно много времени. Даже для числа 265 252 859 812 191 058 636 308 479 999 999 (11*3 = 33 знака) нужно проверить 1,6 * 1016 делителей. И если скорость 2 * 109 / сек, то получаем 1,6 * 1016 / (2 * 109) = 8 * 106 сек или 92 дня.

Вот собственно функции:
mask[i] хранит заранее записанную маску, у которой все единицы начиная от самого левого бита и до i, или по простому - выделяем i бит слева.
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
inline __device__ void Search(ulong a,int n, int &ret)
{
    while (n)
    {
        n >>= 1;
        if (a >> n)
        {
            ret += n;
            a >>= n;
        }
    }
}
 
__device__ void LongMod(ulong *digit, ulong count, ulong modl, int bit, ulong &ret)
{
    int how_bit = BIT;
 
    ulong digit_del = digit[0];
    ulong part = digit[1];
    ulong mod = 0;
 
    mod = digit_del % modl;
    for( ;how_bit > 0; )
    {       
        int bitLeft = 0;
        Search(mod,bit,bitLeft);
        bitLeft = BIT - bitLeft - 1;
        if(how_bit >= bitLeft)
        {
            digit_del = mod << bitLeft;
            digit_del |= (part & mask[bitLeft]) >> (BIT - bitLeft);
            part <<= bitLeft;
            how_bit -= bitLeft;
        }
        else if(how_bit > 0)
        {
            digit_del = mod << how_bit;
            digit_del |= (part & mask[how_bit]) >> (BIT - how_bit);
            how_bit = 0;
        }
        mod = digit_del % modl;
    }
    ret = mod;
}
0
Эксперт С++
 Аватар для Thinker
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
01.11.2012, 19:39  [ТС]
AEXks, ну, ваше стремление похвально, но а на что вы расчитывали, используя длинную арифметику и алгоритм проверки на простоту экспоненциальной сложности относительно количества цифр. Так и должно быть, поэтому я побаловался этим и забросил))
Вы поймите, алгоритм должен зависеть не от аппаратуры (CPU, GPU и т.д.), а от теоретической сложности, а иначе смысла не было бы во многих криптоалгоритмах
0
24 / 3 / 0
Регистрация: 28.10.2012
Сообщений: 35
01.11.2012, 19:43
так алгоритм АКС быстрее это делает?
0
Эксперт С++
 Аватар для Thinker
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
01.11.2012, 19:45  [ТС]
если честно, то не знаю, времени не было его проверить. но у него заявленная сложность полиномиальная относительно количества цифр, то есть обещает быть быстрым. но оять же, не настолько быстрым, чтобы какие-то криптоалгоритмы упали бы.
0
24 / 3 / 0
Регистрация: 28.10.2012
Сообщений: 35
01.11.2012, 20:22
Thinker, может попробуете тогда для CPU реализовать хотя бы?
0
Эксперт С++
 Аватар для Thinker
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
01.11.2012, 21:03  [ТС]
надо будет теоремы почитать с доказательствами, а иначе нет смысла алгоритм составлять. будет время, посмотрю. с другой стороны, почему его так и не реализовали, по крайней мере, не видел реализацию. это, наверное, потому что есть гипотеза (недоказанная), которая значительно ускоряет алгоритм AKS
0
24 / 3 / 0
Регистрация: 28.10.2012
Сообщений: 35
01.11.2012, 21:34
Thinker, на паскале вроде говорят есть реализация
0
Эксперт С++
 Аватар для Thinker
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
01.11.2012, 21:38  [ТС]
AEXks, как же вас зацепила эта задача) может вам имеет смысл в сторону вероятностных алгоритмов посмотреть
0
24 / 3 / 0
Регистрация: 28.10.2012
Сообщений: 35
01.11.2012, 21:47
Thinker, они же не дают точный результат
0
Эксперт С++
 Аватар для Thinker
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
01.11.2012, 21:49  [ТС]
ну, да, а другие алгоритмы (детерминированные) не отличаются скоростью. нужен компромисс)
0
24 / 3 / 0
Регистрация: 28.10.2012
Сообщений: 35
01.11.2012, 21:50
Thinker, а вероятностные на много быстрее?
0
Эксперт С++
 Аватар для Thinker
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
01.11.2012, 21:51  [ТС]
конечно, а иначе не было бы смысла в их использовании.
0
Котовчанин
942 / 482 / 200
Регистрация: 16.02.2010
Сообщений: 3,338
Записей в блоге: 35
22.01.2014, 18:38
Написала когда-то программку, которая, с использованием решета Эратосфена, находит все простые и возвращает самый большой простой делитель числа. Код не идеален, потому как новичок ещё я, но работает быстро.
Буду рада советам!

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <cassert>
#include <math.h>
#include <sstream>
#include <string>
#include <vector>
 
 
std::vector<int> sieve(int num)
{
    int p = 2;
    std::vector <int> s;
    for (int i = 0; i < num; i++)
    {
        s.push_back(i);
    }
    s.at(1) = 1;
 
    while (p < num)
    {
        if (s.at(p)!=0)
        {
        for (int i = p*2; i < num; i += p)
            {
                 s.at(i) = 0;
            }
        }
        p++;
    }
    return s;
}
 
int prime_factor(std::vector<int> vec, unsigned long long div)
{
    int prime = 0;
    for (int i = 0; i < std::sqrtl(div) - 1; i++)
    {
        if (vec.at(i) == 0) {continue;}
        if (div % vec.at(i) == 0)
        {
            prime = vec.at(i);
        }
        i++;
    }
    return prime;
}
 
int solve(unsigned long long num)
{
    std::vector<int> array; 
    int prime;
    int count = std::sqrtl(num);
    array = sieve(count);
    prime = prime_factor(array, num);
    return prime;
}
 
void main(int argc, char *argv[])
{
    unsigned long long arg = 1;
    if (argc >= 1)
    {
        std::stringstream ss;
        ss << argv[1];
        ss >> arg;
    }
    std::cout << solve(arg) << std::endl;
 
}
0
4195 / 1841 / 223
Регистрация: 06.10.2010
Сообщений: 4,127
18.07.2014, 12:07
А все таки как определить номер старшего бита числа
C
1
2
3
4
5
6
7
8
int __declspec(naked) _cdecl bsr(int x)
{
    _asm
    {
        bsr eax,[esp+4]
        ret
    }
}
Добавлено через 9 минут
А ещё на AMD есть какой-то сумасшедший набор инструкций - TBM, возможно его удастся применить к этой задаче.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
18.07.2014, 12:34
Мне кажется, простейший способ - написать прогармму с кодогенерацией, которая сгенерирует метод, который будет проверять все числа Например взять первые 100 простых чисел, и сгенерировать файлик, где
C++
1
2
3
4
5
6
7
8
if (x == a1 || x == a2 || ...)
   return false;
int sqrt = sqrt_int(x);
int step = std::accumulate(...) //тут получаем произведение всех этих простых чисел. Хотя тут уже double наверное нужно юзать, в int вряд ли влезет
for(int i = 0; i < sqrt; i+=)
   if (x%i == 0)
      return false;
return true;
достаточно заранее найти 100 первых простых чисел (тем же эратосфеном).
0
Модератор
Эксперт по электронике
8982 / 6749 / 921
Регистрация: 14.02.2011
Сообщений: 23,875
18.07.2014, 12:48
Цитата Сообщение от Psilon Посмотреть сообщение
достаточно заранее найти 100 первых простых чисел (тем же эратосфеном).
если ты внимательно читал тему то заметил что это уже предлагалось
да и речь то идет не о первых 100 числах а о числах порядка 264 и выше
Цитата Сообщение от murderer Посмотреть сообщение
А ещё на AMD есть какой-то сумасшедший набор инструкций - TBM, возможно его удастся применить к этой задаче.
а еще есть 100500 разных процессоров
решалась задача в общем
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
18.07.2014, 12:57
ValeryS, да, я видел. Но вопрос именно в кодогенерации Прочем не важно. В любом случае для достаточно больших чисел погрешность не даст нормально сказать, какое это число (double без потерь показывает лишь 15 знаков же), а для длинной арифметики слишком много всего писать надо. Вот в лиспе....
0
88 / 84 / 31
Регистрация: 18.11.2013
Сообщений: 390
15.06.2015, 15:03
а можно добавить условие в начало:

if(n%6==1 || n%6==5)
return не простое
else проверять по другому

ну и проверять при помощи деления на числа удовлетворяющие условию

Добавлено через 2 минуты
переходите на java или python, на java есть BigInt, а на python всё вообще динамически расширяется
0
 Аватар для UFO94
267 / 256 / 23
Регистрация: 04.04.2012
Сообщений: 546
17.06.2015, 22:55
Цитата Сообщение от Krock21rus Посмотреть сообщение
if(n%6==1 || n%6==5)
return не простое
else проверять по другому
n=7, n%6=1, n -- простое. Не знаю, может, просто вашу мысль не понял...
0
88 / 84 / 31
Регистрация: 18.11.2013
Сообщений: 390
17.06.2015, 23:44
Ой, извините, наоборот, там надо так:

C++
1
2
3
if(n%6==1 || n%6==5)
Проверять его
else return не простое
вот здесь вы не найдёте примера
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
17.06.2015, 23:44

Проверка числа на простоту
Хочу проверить число на простоту, но не вижу ошибку в коде. Можете подсказать, что не так? #include &lt;iostream&gt; #include...

Проверка числа на простоту
Написать программу, которая запрашивает массив натуральных чисел (ввод с клавиатуры), а затем выводит на экран те элементы массива, которые...

Проверка числа на простоту
Помогите решить 2 задачки, пожалуйста, 1. Написать программу для проверки натурального числа N на простоту. N вводится с клавиатуры. ...

Проверка числа на простоту
я реализовал вот так, но алгоритм очень долгий, мне надо проверять очень большое количество чисел (десятки тысяч) и он так надолго виснет...

Проверка числа на простоту
Дано натуральное число N, проверить, простое оно или нет. Увеличить его значение на натуральное число M. Проверить, осталось ли оно ...


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

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

Новые блоги и статьи
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru