打印64位素数

时间:2014-09-11 13:53:38

标签: c printf primes

#include<stdio.h>
int main(){
    int n,k=1;
    int i,j;
    unsigned long long int sum=0;
    scanf("%d",&n);
    for(i=2;i<n;i++){
        for(j=2;j<=i;j++){
            if(i%j==0)
                k++;
        }
        if(k==2){
            sum=sum+i;
        }
        k=1;
    }
    printf("%lld",sum);
    return 0;
}

此代码适用于输入1000,10000但不适用于100000,1000000,我的意思是它不打印任何内容。 我也试过%I64d但没有用。
如何打印sum

1 个答案:

答案 0 :(得分:3)

我建议你在每次迭代时打印总和而不是在最后,这样你就可以看到计算的进度。除了更容易调试printf语句之外,您还可以检测可能的回绕(例如,如果unsigned long long不足以求和)。

无论如何 - 我认为您的问题实际上与您的printf格式字符串有关:使用%llu代替%lld。请参阅以下代码:

int main(){
    int n,k=1;
    int i,j;
    unsigned long long int sum=0;
    scanf("%d",&n);
    for(i=2;i<n;i++){
        for(j=2;j<=i;j++){
            if(i%j==0)
                k++;
        }
        if(k==2){
            sum=sum+i;
        }
        k=1;
        /* This helps you see what's going on: */
        printf("sum is %llu\n",sum);
    }
    printf("%llu",sum);
    return 0;
}

我使用%llu代替%lld,它运行正常。如果我将其更改回%lld,则每次迭代都不会打印任何内容。

并确保您的输入(n)不得超过平台上int的最大大小。 (但总和可能更大,因为您将其声明为unsigned long long)。

此外,在检查素数时,您可以进行一些基本的优化:

  • 您需要检查的唯一偶数是2.所有其他素数都是奇数。
  • 你不需要检查比n的平方根更远的地方。或者,等效地:假设您正在测试k是否划分n。如果n/k<k(或k*k>n),您可以停止测试。

此外,您可以使用C。

中提供的标准布尔类型

请参阅以下代码中的评论。

#include<stdio.h>
#include<math.h>
/* stdbool defines the type "bool", which can be "true" or "false": */
#include<stdbool.h>

int main(){
    int n;
    int i,j;

    /* prime is initialized to true, since we presume every number is prime
       until we find a divisor for it */
    bool prime = true;

    /* sum is initialized to zero. */
    unsigned long long int sum=0;

    scanf("%d",&n);

    /* If n=2, the result is zero. But if it's greater than two, we need
       to count 2 and start searching from 3. It's easier this way, because then
       we can use i=i+2 in the for loop. */
    if (n>2)
        sum = 2;

    /* no need to count from 2. We start from 3 and count every two numbers. */           
    for(i=3;i<n;i=i+2){
        /* same here. And, since this is the divisor we're looking for, we only 
           need to go up to sqrt(i). We use the long casting here because checking
           j*j<=i would not fit in an int type if j^2 is greater than the maximum
           int. This is a corner case, that happens for example when i is maxint
           (j-1)^2 is below and and j^2 is above it. */
        for(j=3;(long)j*j<=i;j=j+2)
            if(i%j==0) {
                prime = false;
                /* get out, since we already know that this one is composite! */
                break;
            }

        /* no divisors? add it to sum! */
        if (prime)
            sum = sum + i;

        /* reset prime to true, we'll start again with next i */
        prime = true;

        printf("sum is %llu\n",sum);
    }
    printf("%llu\n",sum);
    return 0;
}

这些是您可以做的相当简单的优化。还有其他人,如果你有兴趣,你可以研究sieve of Erathostenes或(如果你是数学倾向),Miller-Rabin test(这不是确定性的,但可能是有意义的)。如果您想使用C库GMP,可以使用Miller-Rabin。