【问题标题】:Find 10000th prime number [duplicate]查找第 10000 个素数 [重复]
【发布时间】:2015-01-03 15:32:46
【问题描述】:

这是我查找第 10000 个素数的代码,但它真的很慢,需要 7 秒来计算。

#include <stdio.h>
#include <stdlib.h>

long int prime (int n)
{
    int i;
    for(i=2;i<n;i++)
    {
        if(n%i==0)
        return 0;
    }
    return 1;
}

int main()
{
    int i=2,counter=0;
    while(1)
    {
        if(prime(i))
        counter++;
        if(counter==10000)
        break;
        i++;
    }
    printf("10000th prime number is: %d",i);
}

这是蛮力方法,所以这可能是它如此缓慢的原因。 我认为问题可能是它必须多次调用函数。那么你认为它可以优化什么,或者最好找到一些数学公式。

【问题讨论】:

标签: c


【解决方案1】:

您可以通过对prime() 进行以下更改来大大减少时间:

  1. 停在sqrt(n)
  2. i=3 开始,以2 递增i

这是一个包含两个版本和每个版本所用时间的程序。

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <math.h>

int is_prime1 (int n)
{
    int i;
    for(i=2;i<n;i++)
    {
        if(n%i==0)
        return 0;
    }
    return 1;
}

void do_it1(int max)
{
   clock_t start = clock();
   clock_t end;

   int i=2,counter=0;
   while(1)
   {
      if(is_prime1(i))
         counter++;
      if(counter==max)
         break;
      i++;
   }
   end = clock();

   printf("%dth prime number is: %d\n", max, i);
   printf("Time taken: %lf\n", 1.0*(end-start)/CLOCKS_PER_SEC);
}

int is_prime2 (int n)
{
    int i;
    int stop = sqrt(n);
    for(i=3;i<=stop;i+=2)
    {
        if(n%i==0)
        return 0;
    }
    return 1;
}

void do_it2(int max)
{
   clock_t start = clock();
   clock_t end;

   int i=3,counter=1;
   while(1)
   {
      if(is_prime2(i))
         counter++;
      if(counter==max)
         break;
      i += 2;
   }
   end = clock();

   printf("%dth prime number is: %d\n", max, i);
   printf("Time taken: %lf\n", 1.0*(end-start)/CLOCKS_PER_SEC);
}

int main(int argc, char** argv)
{
   int max = atoi(argv[1]);
   do_it1(max);
   do_it2(max);
}

示例执行:

./test 10000

样本输出:

10000th prime number is: 104729
Time taken: 9.469000
10000th prime number is: 104729
Time taken: 0.078000

【讨论】:

    【解决方案2】:

    稍微优化您的代码(根据 cmets 进行更改):

    long int prime (int n)
    {
      int i;
      int e = (int)sqrt(n);
      for(i=2; i<=e;i++)
      {
        if(n%i==0)
        return 0;
      }
      return 1;
    }
    

    【讨论】:

    • 你可以忽略2。从i=3; 开始,将i 递增2 以将比较次数减少一半。
    • -1。您还破坏了代码。 sqrt(n) 可能是主要因素。
    • 另外,使用for(int i=2, e=sqrt(n); i &lt;= e; ++i) 避免多次计算平方根。
    【解决方案3】:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    
    int *prime;
    int prime_n;
    
    void make_prime_table(int n){
        prime = malloc(sizeof(int) * n / 2);
        prime_n =0;
        prime[prime_n++] = 2;
        prime[prime_n++] = 3;
        int i, j;
        for(i = 5; i <= n; i +=2){
            bool is_prime = true;
            for(j = 1; j < prime_n ; ++j){
                int t = prime[j];
                if(t * t > i)
                    break;
                if(i % t == 0){
                    is_prime = false;
                    break;
                }
            }
            if(is_prime)
                prime[prime_n++] = i;
        }
    }
    
    int main(void){
        int n = 105000;
        make_prime_table(n);
        if(prime_n >= 10000)
            printf("10000th prime number is: %d\n", prime[9999]);
    
        free(prime);
        return 0;
    }
    
    猜你喜欢
    • 2012-01-07
    • 1970-01-01
    • 2021-08-23
    • 2011-08-29
    • 2019-03-09
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    相关资源
    最近更新 更多