查找Prime Number 10001优化问题

时间:2014-07-22 19:53:15

标签: c

所以我创建了一个找到第10,001个素数的程序。这是该计划的主要内容:

int main(){

  int i;
  int j;
  int count=0;
  int currnumber=0;

  for(i=1; count < 10002; i++){

      if(isPrime(i)){

          count++;
          currnumber = i;

          if(count == 10002)
              printf("%i",currnumber);
      }


  }

}

以下是我在自定义库中构建的IsPrime函数的代码:

long long isPrime(long long number){

    long long i = 2;

    if(number == 2)
        return 1;

    for(i=2;i<number;i++){

        if(number % i == 0)
            return 0;



    }
    if(i >= number && ((number % 1 == 0) && (number % number == 0)))
        return 1;
}

当我运行程序时,它工作并给我正确的答案(这是一个欧拉问题所以我知道我做对了:D),但是至少需要6秒才能处理。所以我的问题是:

  1. 为什么要花这么久?这与我如何设置算法有关吗?
  2. 如何才能改进代码以使其运行得更快?
  3. 提前致谢!

4 个答案:

答案 0 :(得分:1)

您可以做的第一件事就是缓存您创建的素数值,并使用sieve of eratosthenes算法,以便在您找到素数值后不必经常重新计算素数值。< / p>

答案 1 :(得分:1)

您正在使用两个for循环

一种更快的方式出现在我的脑海中并且也是一种很棒的练习算法叫做Sieve of Eratosthenes

答案 2 :(得分:0)

可以做很多优化。有些人提到了Eratosthenes的筛子,这是正确的,但是让我给你一些额外的指示。

在不改变算法的情况下改进代码:正如Michael Parker所提到的,你不需要处理偶数,因为只有其中一个是素数(数字2,这使得它成为&# 39;最奇怪的是 - 这是一个双关语。你可以通过避免三的倍数来做类似的技巧,这可以归结为仅处理整数i,它比6的倍数多1或5个。要将其转换为代码,首先设置{{1} }到3来计算素数2,3和5.然后在6处开始count并测试ii+1(都在i+5循环内),并且然后每次将for增加6。

对于i,您可以添加类似的改进,但是一旦达到该数字的平方根,您也可以停止试验分割。这是因为当且仅当它具有除数&lt; = sqrt(数字)时,isPrime()才有除数&gt; = number。要证明这一点,关键是如果sqrt(number)a,那么number就是另一个除数(你可以填写剩余的细节,因为你很聪明)。

使用Sieve of Eratosthenes来改善您的代码:正如许多人所提到的,Eratosthenes的筛子更能解决这个问题。事实上,它是超级快速的。但是经常被忽视的一个问题是你的筛子长度有多大,以确保你捕获了你所追求的素数,却没有让它变得非常大? Prime Number Theorem估计应该有多大。但是你需要一个upper bound。建议使用n *(ln n * ln ln n)。

答案 3 :(得分:0)

如果我理解正确,你会将每个数字小于1001,并检查它是否有共同点。这非常慢。复杂性实际上呈指数级增长。你应该做的是将这种方法与筛子结合起来。使用公分母方法得到任何素数,然后将它们从1乘以n,直到你得到1到10001之间的所有倍数。这样你就可以跳过在你已经存在的所有素数的倍数上测试公分母方法找到。例如,试试这个:

ArrayList<Integer> List = new ArrayList<Integer>();
ArrayList<Integer> Primes = new ArrayList<Integer>();
Primes.add(2);
Integer p=2;
Integer n=105000;
Integer i=1;

while(p < n) {
    i=1;
    while((p*i)<=n){
        List.add(p*i);
        i++;
    }
    while (p < n){
    p++;
    if(List.contains(p)){}
    else {Primes.add(p); break;}
    }
}

System.out.println(Primes.get(10000));