使用C ++找出质数最快的算法是哪一种?我已经使用了sieve的算法,但我仍然希望它更快!
使用C ++找出质数最快的算法是哪一种?我已经使用了sieve的算法,但我仍然希望它更快!
Answers:
丹·伯恩斯坦(Dan Bernstein)的primegen 是阿特金筛网(Sieve of Atkin)的非常快速的实现。该筛子比Eratosthenes筛子更有效。他的页面上有一些基准信息。
如果必须非常快,则可以包含素数列表:http :
//www.bigprimes.net/archive/prime/
如果您只想知道某个数字是否是质数,那么Wikipedia上列出了各种素数测试。它们可能是确定大数是否为质数的最快方法,尤其是因为它们可以告诉您数字是否不是质数。
他,他,我知道我是一个死灵法师,正在回答旧问题,但是我刚刚发现这个问题正在网上搜索实现有效质数测试的方法。
到目前为止,我相信最快的质数测试算法是强概率质数(SPRP)。我引用Nvidia CUDA论坛:
数论中较实际的利基问题之一与质数的确定有关。给定N,您如何有效确定其是否为质数?这不仅是一个理论上的问题,而且可能是代码中真正需要的一个问题,也许当您需要动态地找到特定范围内的原始哈希表大小时。如果N为2 ^ 30的数量级,您是否真的要进行30000个除法测试以查找任何因子?显然不是。
解决此问题的常用方法是使用一个简单的测试(称为Euler可能素数测试)和一个更强大的概括(称为强概率素数(SPRP))。这是一个对于整数N可以概率性地将其分类为质数或不存在质数的测试,重复测试可以提高正确性的可能性。测试本身的较慢部分主要涉及计算类似于A ^(N-1)模N的值。实现RSA公钥加密变体的任何人都使用了此算法。对于巨大的整数(例如512位)以及普通的32位或64位整数,它都非常有用。
通过预先计算已知在N范围内总是成功的某些测试输入参数,可以将测试从概率拒绝更改为确定性的原始证明。不幸的是,发现这些“最知名的测试”实际上是在寻找巨大的(实际上是无限的)域。1980年,卡尔·波莫兰斯(Carl Pomerance)创建了第一个有用的测试列表(以使用二次方Seive算法而成为RSA-129的分解因子而闻名)。后来的杰斯凯(Jaeschke)于1993年对结果进行了重大改进。2004年,张和唐改进了这一理论。和搜索域的限制。到目前为止,Greathouse和Livingstone已在http://math.crg4.com/primes.html上发布了最新的搜索结果,这是一个庞大的搜索域中的最佳搜索结果。
有关更多信息,请参见此处:http : //primes.utm.edu/prove/prove2_3.html和http://forums.nvidia.com/index.php?showtopic=70483
如果您只需要一种生成非常大的素数的方法,而又不想生成所有小于整数n的素数,则可以使用Lucas-Lehmer测试来验证Mersenne素数。Mersenne质数的形式为2 ^ p -1。我认为Lucas-Lehmer检验是针对梅森质数的最快算法。
而且,如果您不仅要使用最快的算法,还要使用最快的硬件,请尝试使用Nvidia CUDA来实现它,为CUDA编写内核并在GPU上运行它。
如果发现足够大的素数,您甚至可以赚到一些钱,EFF提供的奖金从$ 50K到$ 250K:https: //www.eff.org/awards/coop
有一个100%数学测试将检查数字P
是素数还是合成数,称为AKS Primality Test。
概念很简单:给定一个数字P
,如果的所有系数(x-1)^P - (x^P-1)
都可被整除P
,P
则为质数,否则为合成数。
例如,给定P = 3
,将给出多项式:
(x-1)^3 - (x^3 - 1)
= x^3 + 3x^2 - 3x - 1 - (x^3 - 1)
= 3x^2 - 3x
并且系数都可以被整除3
,因此数字为素数。
举个例子P = 4
,其中不是素数的会产生:
(x-1)^4 - (x^4-1)
= x^4 - 4x^3 + 6x^2 - 4x + 1 - (x^4 - 1)
= -4x^3 + 6x^2 - 4x
在这里我们可以看到系数6
不能被整除4
,因此不是素数。
多项式(x-1)^P
将成为P+1
项,并且可以使用组合找到。因此,此测试将在O(n)
运行时运行,因此我不知道这将有多大用处,因为您可以简单地i
从0 迭代到p
其余部分并进行测试。
x
代表什么?在中(x-1)^P - (x^P-1)
。您是否有示例代码?在C ++中确定整数是否为质数?
您是否要确定某个数字是否为质数?然后,您需要进行素数测试(简单)。还是您需要所有给定数的素数?在那种情况下,主要的筛子是好的(容易,但需要记忆)。还是您需要数字的主要因素?这将需要分解(如果您确实想要最有效的方法,则很难进行大量分解)。您要查看的数字有多大?16位?32位?大?
一种聪明而有效的方法是预先计算素数表,并使用位级编码将它们保存在文件中。该文件被视为一个长位向量,而位n代表整数n。如果n为质数,则其位设置为1,否则设置为0。查找速度非常快(您可以计算字节偏移量和位掩码),并且不需要将文件加载到内存中。
Rabin-Miller是标准的概率素数测试。(您将其运行了K次,并且输入数字肯定是复合数字,或者它可能是素数,出现错误的可能性为4 -K。(几百次迭代,几乎可以肯定地说出了真相)
Rabin Miller有一个非概率(确定性)变体。
在互联网梅森素数大搜索已找到了世界对大探明黄金记录(GIMPS)(2 74207281 - 1 6月2017),采用多种算法,但这些都是特殊形式的素数。但是,上面的GIMPS页面确实包含一些常规的确定性素数测试。它们似乎表明哪种算法“最快”取决于要测试的数字的大小。如果您的数字适合64位,那么您可能不应该使用旨在处理数百万个质数的方法。
我总是使用这种方法来计算筛子算法之后的素数。
void primelist()
{
for(int i = 4; i < pr; i += 2) mark[ i ] = false;
for(int i = 3; i < pr; i += 2) mark[ i ] = true; mark[ 2 ] = true;
for(int i = 3, sq = sqrt( pr ); i < sq; i += 2)
if(mark[ i ])
for(int j = i << 1; j < pr; j += i) mark[ j ] = false;
prime[ 0 ] = 2; ind = 1;
for(int i = 3; i < pr; i += 2)
if(mark[ i ]) ind++; printf("%d\n", ind);
}
我会让你决定是否最快。
using System;
namespace PrimeNumbers
{
public static class Program
{
static int primesCount = 0;
public static void Main()
{
DateTime startingTime = DateTime.Now;
RangePrime(1,1000000);
DateTime endingTime = DateTime.Now;
TimeSpan span = endingTime - startingTime;
Console.WriteLine("span = {0}", span.TotalSeconds);
}
public static void RangePrime(int start, int end)
{
for (int i = start; i != end+1; i++)
{
bool isPrime = IsPrime(i);
if(isPrime)
{
primesCount++;
Console.WriteLine("number = {0}", i);
}
}
Console.WriteLine("primes count = {0}",primesCount);
}
public static bool IsPrime(int ToCheck)
{
if (ToCheck == 2) return true;
if (ToCheck < 2) return false;
if (IsOdd(ToCheck))
{
for (int i = 3; i <= (ToCheck / 3); i += 2)
{
if (ToCheck % i == 0) return false;
}
return true;
}
else return false; // even numbers(excluding 2) are composite
}
public static bool IsOdd(int ToCheck)
{
return ((ToCheck % 2 != 0) ? true : false);
}
}
}
在配备2.40 GHz处理器的Core 2 Duo笔记本电脑上,查找和打印1至1,000,000范围内的质数大约需要82秒。它发现了78,498个质数。
i <= (ToCheck / 3)
。应该是i <= (ToCheck / i)
。使用它,它可能会在0.1秒内运行。
#include<stdio.h>
main()
{
long long unsigned x,y,b,z,e,r,c;
scanf("%llu",&x);
if(x<2)return 0;
scanf("%llu",&y);
if(y<x)return 0;
if(x==2)printf("|2");
if(x%2==0)x+=1;
if(y%2==0)y-=1;
for(b=x;b<=y;b+=2)
{
z=b;e=0;
for(c=2;c*c<=z;c++)
{
if(z%c==0)e++;
if(e>0)z=3;
}
if(e==0)
{
printf("|%llu",z);
r+=1;
}
}
printf("|\n%llu outputs...\n",r);
scanf("%llu",&r);
}
我不知道任何预定义的算法,但是我创建了自己的算法,速度非常快。它可以在不到1秒的时间内处理20位数字。该程序的最大容量为18446744073709551615。该程序是:
#include <iostream>
#include <cmath>
#include <stdlib.h>
using namespace std;
unsigned long long int num = 0;
bool prime() {
if (num % 2 == 0 || num == 1) {
return false;
}
unsigned long int square_root = sqrt(num);
for (unsigned long int i = 3; i <= square_root; i += 2) {
if (num % i == 0) {
return false;
}
}
return true;
}
int main() {
do {
system("cls");
cout << "Enter number : ";
cin >> num;
if (prime()) {
cout << "The number is a prime number" << endl << endl << endl << endl;
} else {
cout << "The number is not a prime number" << endl << endl << endl << endl;
}
system("pause");
} while (1);
return 0;
}
#include <iostream>
using namespace std;
int set [1000000];
int main (){
for (int i=0; i<1000000; i++){
set [i] = 0;
}
int set_size= 1000;
set [set_size];
set [0] = 2;
set [1] = 3;
int Ps = 0;
int last = 2;
cout << 2 << " " << 3 << " ";
for (int n=1; n<10000; n++){
int t = 0;
Ps = (n%2)+1+(3*n);
for (int i=0; i==i; i++){
if (set [i] == 0) break;
if (Ps%set[i]==0){
t=1;
break;
}
}
if (t==0){
cout << Ps << " ";
set [last] = Ps;
last++;
}
}
//cout << last << endl;
cout << endl;
system ("pause");
return 0;
}
(n%2)+1+(3*n)
虽然很好。:)
我知道会晚一些,但是这对于从搜索中到达这里的人们可能很有用。无论如何,这里有一些JavaScript依赖于这样一个事实,即仅需要测试素数因子,因此,由代码生成的较早素数将被重新用作后面的素数。当然,所有偶数和mod 5值都将首先被滤除。结果将在数组P中,并且此代码可以在i7 PC上在1.5秒内处理1000万个质数(或在20个左右中处理1亿个质数)。用C重写它应该非常快。
var P = [1, 2], j, k, l = 3
for (k = 3 ; k < 10000000 ; k += 2)
{
loop: if (++l < 5)
{
for (j = 2 ; P[j] <= Math.sqrt(k) ; ++j)
if (k % P[j] == 0) break loop
P[P.length] = k
}
else l = 0
}
#include<iostream>
using namespace std;
void main()
{
int num,i,j,prime;
cout<<"Enter the upper limit :";
cin>>num;
cout<<"Prime numbers till "<<num<<" are :2, ";
for(i=3;i<=num;i++)
{
prime=1;
for(j=2;j<i;j++)
{
if(i%j==0)
{
prime=0;
break;
}
}
if(prime==1)
cout<<i<<", ";
}
}
break;
它会更慢,O(N ^ 2),但这已经可以看作是编码错误。通过质数的保存和测试为O(N ^ 2 /(log N)^ 2),仅在数字的平方根以下的质数进行测试是O(N ^ 1.5 /(log N)^ 2)。