c中的eratosthenes筛选

时间:2014-06-09 11:44:11

标签: c++ c algorithm math sieve-of-eratosthenes

这是我在C中筛选eratosthenes的代码。 它给了我以下输出。

2 3 五 7 11 13 17 19 23 25 31 35 37 41 43 47

我的输出包括25和35也不是素数,它不包括29。

谁能告诉我哪里错了。

#include<stdio.h>
#include<math.h>
int main()
{
    int i,a[50],b[50],j,n=0,s;
    for(i=0;i<50;i++)
        a[i] = 1;
    a[0]=a[1] = 0;

    for(i=2;i<50;i++)
        if(a[i])
            for(j=pow(i,2);j<50;j+=i)
                a[j] = 0;

    for(i=0;i<50;i++)
        if(a[i])
        {
            b[n] = i;
            n++;
        }

    for(j=0;j<n;j++)
        printf("%d\n",b[j]);
    return 0;
}

4 个答案:

答案 0 :(得分:6)

使用gcc版本4.4.7(Ubuntu / Linaro 4.4.7-2ubuntu1)编译,您的代码返回正确的结果。该问题可能与编译器和pow()实现有关。

可能您有pow的天真实施,将pow(x,y)计算为exp(y*log(x))。这是浮点运算,它遇到常见的浮点问题。这意味着pow(x,y)转换为整数的结果将被截断,因为双重算术log(x)*y和取幂将返回略小于整数x*y的double值。

将代码更改为

for( j = i * i; j < 50; j += i)
    a[j] = 0;

此外,我们只能迭代直到sqrt(n),因为第二个循环才会被执行:

for( i = 2; i < sqrt(50); i++)
    if( a[i]) // if not marked
        /* mark starting from i*i because i*j for j<i
         * has been already marked when i was j */
        for( j = i * i; j < 50; j += i)
            a[j] = 0; 

相关问题:code blocks power function is not working in c

答案 1 :(得分:4)

正如其他人所观察到的那样,错误发生在pow函数中。我无法使用您显示的代码重现您的错误,但是当我推出自己的ppow函数时:

double ppow(double a, double x)
{
    return exp(log(a) * x);
}

我的名单与你的名单相符。我认为pow的符合标准的实现应该将整数指数视为可以采用负基的特殊情况,因此pow似乎不符合。

而不是pow(i, 2),请使用i*i。这应该更快,你也不必链接到数学库。

答案 2 :(得分:2)

我尝试重现你的输出,但我不能。

操作系统信息:

  

$ uname -a Linux 3.13.0-29-generic#53-Ubuntu SMP Wed Jun 4   21:00:20 UTC 2014 x86_64 x86_64 x86_64 GNU / Linux

编译器信息:

  

$ gcc --version gcc(Ubuntu 4.8.2-19ubuntu1)4.8.2

编译:

  

$ gcc sieve_of_eratosthenes.c -lm -o sieve_of_eratosthenes

启动:

  

$ ./sieve_of_eratosthenes

     

2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

答案 3 :(得分:0)

pow函数使用处理器上的浮点单元时,它可能会产生异常。

在执行此函数期间发生此类异常时,可能会返回不正确的值。

当您pow(i,2)i等于5时,系统可能就是这种情况。

作为支持这一猜想的间接证据,请注意每个数字(在[0-49]的指定范围内)是 5和素数大于5 的倍数,在你的素数列表上。


以下是一段代码,用于检索因FP操作而可能发生的异常:

#include <fenv.h>
#include <stdio.h>

void print_fe_exceptions()
{
    printf("Exceptions raised:");
    if (fetestexcept(FE_DIVBYZERO)) printf(" FE_DIVBYZERO");
    if (fetestexcept(FE_INEXACT  )) printf(" FE_INEXACT  ");
    if (fetestexcept(FE_INVALID  )) printf(" FE_INVALID  ");
    if (fetestexcept(FE_OVERFLOW )) printf(" FE_OVERFLOW ");
    if (fetestexcept(FE_UNDERFLOW)) printf(" FE_UNDERFLOW");
    feclearexcept(FE_ALL_EXCEPT);
    printf("\n");
}

以下是每个例外情况的描述:

FE_DIVBYZERO // Pole error occurred in an earlier floating-point operation
FE_INEXACT   // Inexact result: rounding was necessary to store the result of an earlier floating-point operation
FE_INVALID   // Domain error occurred in an earlier floating-point operation
FE_OVERFLOW  // The result of an earlier floating-point operation was too large to be representable
FE_UNDERFLOW // The result of an earlier floating-point operation was subnormal with a loss of precision