Моя собственная функция IsPrime (), написанная и основанная на детерминированном варианте известного алгоритма Рабина-Миллера, в сочетании с оптимизированным пошаговым форсированием, предоставляя вам одну из самых быстрых простых функций тестирования.
__int64 power(int a, int n, int mod)
{
__int64 power=a,result=1;
while(n)
{
if(n&1)
result=(result*power)%mod;
power=(power*power)%mod;
n>>=1;
}
return result;
}
bool witness(int a, int n)
{
int t,u,i;
__int64 prev,curr;
u=n/2;
t=1;
while(!(u&1))
{
u/=2;
++t;
}
prev=power(a,u,n);
for(i=1;i<=t;++i)
{
curr=(prev*prev)%n;
if((curr==1)&&(prev!=1)&&(prev!=n-1))
return true;
prev=curr;
}
if(curr!=1)
return true;
return false;
}
inline bool IsPrime( int number )
{
if ( ( (!(number & 1)) && number != 2 ) || (number < 2) || (number % 3 == 0 && number != 3) )
return (false);
if(number<1373653)
{
for( int k = 1; 36*k*k-12*k < number;++k)
if ( (number % (6*k+1) == 0) || (number % (6*k-1) == 0) )
return (false);
return true;
}
if(number < 9080191)
{
if(witness(31,number)) return false;
if(witness(73,number)) return false;
return true;
}
if(witness(2,number)) return false;
if(witness(7,number)) return false;
if(witness(61,number)) return false;
return true;
/*WARNING: Algorithm deterministic only for numbers < 4,759,123,141 (unsigned int's max is 4294967296)
if n < 1,373,653, it is enough to test a = 2 and 3.
if n < 9,080,191, it is enough to test a = 31 and 73.
if n < 4,759,123,141, it is enough to test a = 2, 7, and 61.
if n < 2,152,302,898,747, it is enough to test a = 2, 3, 5, 7, and 11.
if n < 3,474,749,660,383, it is enough to test a = 2, 3, 5, 7, 11, and 13.
if n < 341,550,071,728,321, it is enough to test a = 2, 3, 5, 7, 11, 13, and 17.*/
}
Чтобы использовать, скопируйте и вставьте код в верхнюю часть вашей программы. Вызовите его, и он вернет значение BOOL, истинное или ложное.
if(IsPrime(number))
{
cout << "It's prime";
}
else
{
cout<<"It's composite";
}
Если вы столкнулись с проблемой компиляции с помощью «__int64», замените ее на «long». Прекрасно компилируется под VS2008 и VS2010.
Как это работает:
Эта функция состоит из трех частей. Деталь проверяет, является ли оно одним из редких исключений (отрицательные числа, 1), и перехватывает выполнение программы.
Вторая часть начинается, если число меньше 1373653, что является теоретическим числом, в котором алгоритм Рабина Миллера превзойдет мою оптимизированную функцию грубой силы. Затем идут два уровня Рабина Миллера, предназначенные для сведения к минимуму необходимого числа свидетелей. Поскольку большинство чисел, которые вы будете тестировать, составляют менее 4 миллиардов, вероятностный алгоритм Рабина-Миллера можно сделать детерминированным, проверив свидетелей 2, 7 и 61. Если вам нужно преодолеть 4 миллиарда, вам понадобится большой библиотеки чисел и примените модификацию модуля или сдвига бита к функции power ().
Если вы настаиваете на методе грубой силы, вот только моя оптимизированная функция IsPrime () для грубой силы:
inline bool IsPrime( int number )
{
if ( ( (!(number & 1)) && number != 2 ) || (number < 2) || (number % 3 == 0 && number != 3) )
return (false);
for( int k = 1; 36*k*k-12*k < number;++k)
if ( (number % (6*k+1) == 0) || (number % (6*k-1) == 0) )
return (false);
return true;
}
}
Как работает этот перебор:
Все простые числа (кроме 2 и 3) могут быть выражены в виде 6k + 1 или 6k-1, где k - целое положительное число. Этот код использует этот факт и проверяет все числа в форме 6k + 1 или 6k-1 меньше, чем квадратный корень из рассматриваемого числа. Эта часть интегрирована в мою большую функцию IsPrime () (функция, показанная первой).
Если вам нужно найти все простые числа ниже числа, найдите все простые числа ниже 1000, посмотрите на Сито Эратосфена. Еще один мой любимый.
В качестве дополнительного примечания, я хотел бы, чтобы кто-нибудь реализовал алгоритм Eliptical Curve Method, давно хотел увидеть его реализованный в C ++, и я потерял свою реализацию. Теоретически, это даже быстрее, чем детерминированный алгоритм Рабина Миллера, который я реализовал, хотя я не уверен, верно ли это для чисел до 4 млрд.