使用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)。