C++ c中埃拉托斯烯的筛分
这是我在C语言中对埃拉托斯烯进行筛选的代码。 它给了我以下输出 二, 3. 5. 7. 11 13 17 19 23 25 31 35 37 41 43 47 我的输出也包括25和35,它们不是素数,也不包括29 谁能告诉我哪里错了C++ c中埃拉托斯烯的筛分,c++,c,algorithm,math,sieve-of-eratosthenes,C++,C,Algorithm,Math,Sieve Of Eratosthenes,这是我在C语言中对埃拉托斯烯进行筛选的代码。 它给了我以下输出 二, 3. 5. 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;
#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;
}
#包括
#包括
int main()
{
int i,a[50],b[50],j,n=0,s;
对于使用gcc版本4.4.7(Ubuntu/Linaro 4.4.7-2ubuntu1)编译的(i=0;i),您的代码返回正确的结果。问题可能与编译器和pow()实现有关
可能您有一个简单的pow
实现,它将pow(x,y)
计算为exp(y*log(x))
。这是浮点运算,它存在常见的浮点问题。这意味着pow(x,y)
转换为整数的结果将被截断,因为双算术log(x)*y
和将返回略小于整数x*y的双倍值的幂运算
将代码更改为
for( j = i * i; j < 50; j += i)
a[j] = 0;
(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;
for(i=2;i /*标记从i*i开始,因为i*j代表j我试图重现您的输出,但我不能
操作系统信息:
$uname-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——gcc版本(Ubuntu 4.8.2-19ubuntu1)4.8.2
汇编:
$gcc-埃拉托斯坦筛余物。c-lm-o-埃拉托斯坦筛余物
发布:
美元/筛除埃拉托斯坦
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
正如其他人所观察到的,错误出现在pow
函数中。我无法用您显示的代码重现您的错误,但当我滚动自己的ppow
函数时:
double ppow(double a, double x)
{
return exp(log(a) * x);
}
我的列表与您的列表相匹配。我认为pow
的标准一致性实现应该将整数指数视为一种特殊情况,可以采用负基数,因此您的pow
似乎不一致
使用i*i
而不是pow(i,2)
。这应该更快,而且您也不必链接到数学库。当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");
}
我无法重现该错误。可能您有不同的pow()
实现。请尝试I*I
。我也一样。请指定编译器版本和更多环境详细信息。编译时不使用优化标志(如果是gcc)请指定不相关的编译器,但我建议使用更多的描述性变量名,而不是作为注释的a
和b
。我的费率不允许我留下注释。2*I
在I
为2
时已被标记为非素数。3*I
和4*I
的情况类似,等等。从i*i
@bits\u international开始就足够了,但这仍然不是问题的答案。事实上,我们正在处理算法以外的其他问题。是的,代码块的pow实现是问题所在。感谢链接。我随时为您服务,我的好先生谢谢您,使用i*i代替pow(i,2)解决了我的问题,但我仍然无法理解为什么pow(I,2)给了我错误的答案。pow
适用于浮点数。它们不精确,当它们是上面ppow
实现中的计算结果时更是如此。对于ppow(20,2)
我得到了399.9999999999,例如,转换为int后将变成399。您可能不需要舍入:ppow(I,2)+0.5
,但我建议对整数幂使用简单乘法,特别是对于像平方这样的简单幂。ppow()和pow()之间的区别是什么.pow
是您的数学库的幂函数。ppow
是我上面使用的pow
的实现。它不是符合标准的实现,但我假设您使用的数学库以这种方式实现了pow
。我使用ppow
表示编译器的pow
可能是破碎的
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