Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.68/735: Рейтинг темы: голосов - 735, средняя оценка - 4.68
Эксперт С++
 Аватар для Thinker
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5

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

29.09.2012, 21:35. Показов 146441. Ответов 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
Ответ Создать тему
Новые блоги и статьи
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
rest api anylogic - выполнение модели на своём русском сайте
anaschu 02.07.2026
Как подружиться с AnyLogic Cloud API, победить провайдеров и развернуться Java-бэкенд в Docker на бесплатном хостинге: Двухдневный лог борьбы Всем привет! Хочу поделиться свежим (и довольно. . .
Где деньги лежат
kumehtar 02.07.2026
Это - японская подводная лодка I-52 (тип C2, кодовое имя Momi) вышла из Японии в марте 1944 года с миссией в оккупированную немцами Францию (Лорьян). Это была одна из «Янаги»-миссий по обмену. . .
Krabik для WoW 3.3.5a, многоязычный
AmbA 02.07.2026
Допилил бота, думаю что окончательно. Изменения: - добавлена многоязычность - добавлено снятие скриншотов - добавлено поддержание бафов хождения по воде (для жреца, дк и шамана) - и так, по. . .
Алиса нашла кучу ошибок компиляции и запуска в проекте, который без проблем компилировался и запускался)))
anaschu 30.06.2026
Я пока посмеюся, но завтра проверю. А вообще интерсно. Дал алисе файл, в котором точно нет ошибок компиляции и запуска, и попросил их найти. Нашла кучу))) Критические ошибки, мешающие компиляции и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru