【问题标题】:Faster way to find Nth prime找到第 N 个素数的更快方法
【发布时间】:2017-03-16 02:02:32
【问题描述】:

我最近试图浏览我书中的 100 个不同练习的列表,目前是第 23 号。找到第 N 个素数,虽然这看起来很容易,但我注意到搜索更大的数字需要很长时间数字(又名 50000 大约需要 47 秒。

#include <iostream>
#include <time.h>

using namespace std;
bool checkPrime(int n);

int main()
{   
    while (true)
    {       
        register int number;
        cin >> number;
        register int counter = 0;
        register int numbers = 0;
        time_t start = clock();
        while (counter < number)
        {
            numbers++;
            if (checkPrime(numbers))counter++;
        }
        double time_diff = (clock() - start);
        cout << numbers << endl;
        cout << "Time needed to process in ms: " << time_diff << endl;
    }
}


bool checkPrime(int n) {
    if (n <= 1) return false;
    for (register int i = 2; i < n; i++) {
        if (n%i == 0)return false;
    }
    return true;
}

这是代码本身,没什么花哨的,因为它仍然是更简单的练习之一,尝试将变量设置为寄存器,因为我听说它有时会使事情变得更快。 WolframAlpha 需要大约 10 秒来检查第 100.000 个素数,我的代码需要大约 90 秒。提前感谢 Folling

【问题讨论】:

  • 埃拉托色尼筛是一种常见的方法来找到所有合理的小素数,直到某个限制。查一下,它很可能比你当前的实现要快。
  • 提示:你的 checkPrime 是 O(n),它可以很容易变成 O(sqrt(n))。 (这里的 n 是数字 n,而不是它的位数)
  • @moreON 是正确的——我不久前写了一个 C 程序,它使用 Etatosthenes 的筛子解决了这个问题。找到第 100,000 个素数大约需要 16 毫秒,而找到第 100,000 个素数则不到 0.2 秒。您可以使用prime number theorem 计算所需的数字筛大小。
  • 有空间限制吗?
  • 这个已经讨论过很多次了...

标签: c++ algorithm primes


【解决方案1】:

如果您没有空间限制,请创建一个包含素数的向量并更改您的 checkPrime 方法,如下所示:

vector<int> primes;
bool checkPrime(int n) {
     if (n <= 1) return false;
     for (int i = 0; i < primes.size(), primes.at(i) <= sqrt(n); i++) {

          if (n%primes.at(i)== 0)
               return false;
     }
     primes.push_back(n)
     return true;
}

通过这种技术,您将只检查 n 是否可以被素数整除,而不是检查直到其平方根的所有数字。

在这里,我们利用一个数字是素数或一个或多个素数的倍数。

CheckPrime 方法是 O(log n),所以找到前 N 个素数是 O(n log n) 其中 n 是第 N 个素数的值

【讨论】:

    【解决方案2】:

    试试这个:

    #include <iostream>
    #include <time.h>
    #include <vector>
    #include <math.h>
    
    using namespace std;
    inline bool checkPrime(int n,std::vector<int>);
    
    int main()
    {
        int number,counter,numbers;
        std:cout<<"Prime Searcher";
        std::vector<int> sieve;
    
    
        while (true)
        {
    
            cin >> number;
            counter = 0;
            numbers = 0;
            time_t start = clock();
            while (counter < number)
            {
                if (numbers>2){
                    numbers+=2;
                }
                else{
                    numbers++;
                }
                if (checkPrime(numbers,sieve)){
                    sieve.push_back(numbers);
                    counter++;
                }
    
                }
            double time_diff = (clock() - start);
            cout << numbers << endl;
            cout << "Time needed to process in seconds: " << time_diff/CLOCKS_PER_SEC << endl;
        }
    }
    
    
    inline bool checkPrime(int n, std::vector<int> sieve) {
        double numPrimes=(sqrt(n)/log(sqrt(n))+3);
        if (numPrimes>sieve.size()){numPrimes=sieve.size();}
        if (n <= 1) return false;
        for (int i = 2; i < numPrimes; i++) {
            if (n%sieve[i] == 0)return false;
        }
        return true;
    }
    

    根据我的基准测试,对于 n=4000,这是超过 2 倍的优化,并且随着数字的增加而增加。 register 已折旧。任何有关如何进一步优化的建议将不胜感激。在 n=50000 时,我的机器需要 24 秒。

    【讨论】:

      【解决方案3】:

      这是锻炼和非常大的数字的好方法

      bool chekPrime(unsigned long long int n){
      int flag=0;            //flag=0 => flag is not set
      if(n<=1||n%2==0)flag=1;//flag=1 => n is not prime
      if(n==2||n==3)flag=2;  //flag=2 => n is prime
      if(flag==0){
          for(unsigned long long int i=3;i*i<=n;i+=2){
              if(n%i==0){
                  flag=1;//flag=1 => n is not prime
                  break;
              }
          }
      }
      //if flag not set or flag=2 => n is prime
      if(flag==0||flag==2)return true;
      else return false;
      

      }

      【讨论】:

        猜你喜欢
        • 2017-11-27
        • 1970-01-01
        • 2015-06-19
        • 2013-01-22
        • 2016-02-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-07
        • 1970-01-01
        相关资源
        最近更新 更多