对于此函数,计算woodall数字直至n = 64
Woodall的算法为Wn = n⋅2n-1
for (int n = 1; n <= 64; ++n)
{
a[n - 1] = (n * (exp2(n))) - 1;
}
但是在
n
大于47之后,结果是错误的,因为似乎忘记了- 1
的结果是n * (exp2(n))
。如果我通过
cout
值,这就是输出std::cout << i << ":\t" << std::setprecision(32) << a[i - 1] << std::endl;
...之前是正确的
n
45: 1583296743997439
46: 3236962232172543
47: 6614661952700415
48: 13510798882111488
49: 27584547717644288
50: 56294995342131200
...之后不正确
for
a[]
是一个无符号的long int如果我将
- 1
操作分离为自己的for循环,则该函数将产生正确的结果:for (int n = 1; n <= 64; ++n)
{
a[n - 1] = (n * (exp2(n)));
}
for (int n = 1; n <= 64; ++n)
{
a[n - 1] = a[n - 1] - 1;
}
最佳答案
exp2(n)
返回一个double
。
在IEEE754(一种非常常见的浮点类型规范)中,它仅给您精确的整数,直到52的2的幂。
由于整个隐式类型转换,整个表达式n * (exp2(n))) - 1
是double
,因此您会在第52 Woodall号之前观察到问题。 通过计算古怪,是导致问题的-1。恰巧另一个项是2的幂的适当倍数,这使其可以表示为没有精度损失的 double ! ,这是第二个代码段正常运行的原因,而第一个代码段无效。
在具有64位int
的系统上,您将以63的2的幂来达到整数限制(和未定义的行为)。
最好的选择是纯粹用unsigned
算术生成Woodall数(请注意<<
与2的幂之间的关系),甚至可能对连续的Woodall数使用递归关系。
关于c++ - 在n> 47之后,为什么我计算woodall数的程序为什么会产生错误的结果?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53266239/