c++ - 为什么我的 Woodall 数计算程序在 n >47 后产生错误的结果?

标签 c++ math icc

此函数计算 n = 64 以内的 woodall 数

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))的结果.

以下是如果 i 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

...之后不正确

对于a[]是一个无符号长整型

如果我分离- 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(浮点类型的一种非常常见的规范)中,它只能为您提供 2 的 52 次方以内的精确整数。此后您将获得近似值。

自整个表达式 n * (exp2(n))) - 1 以来,您观察到第 52 个 Woodall 数字之前的问题是 double由于隐式类型转换。 由于计算上的怪癖,导致问题的是 -1。只是碰巧另一个项是 2 的幂的适当倍数,这使得它可以表示为 double 而不损失精度!这就是你的第二个片段工作但你的第一个片段不工作的原因。 p>

在 64 位系统上 int ,您将达到 2 的 63 次方的整数限制(和未定义的行为)。

您最好的选择是纯粹在 unsigned 中生成伍德尔数。算术(注意 << 和 2 的幂之间的关系),甚至可能对连续的 Woodall 数使用递归关系。

关于c++ - 为什么我的 Woodall 数计算程序在 n >47 后产生错误的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53266239/

相关文章:

optimization - 如何在 AMD 芯片上使用英特尔编译器优化 C++ 程序

c++ - Visual Studio 中的内存泄漏

c++ - fwrite 字符串中的二进制数据

c++ - 从成员类访问非静态属性

c++ - 为 unordered_set 重载 () 运算符

algorithm - 如何以最佳方式更改 item.OrderNum 字段以匹配列表顺序

javascript - 什么数学工具类似于 JavaScript 对象?

c - 生成由编译器定义的预处理器宏列表

c - 不同架构的集群应该指定哪个AVX和march?

python - 点 [4, 7] 与以 [2, 9] 为圆心、半径为 2 的圆上最近的点之间的距离是多少?提供至少 4 位数字的准确度