【发布时间】:2015-03-29 23:00:18
【问题描述】:
我正在尝试编写一个简单的 log base 2 方法。我知道在计算机上表示 std::log(8.0) 和 std::log(2.0) 之类的东西很困难。我也了解 std::log(8.0) / std::log(2.0) 可能会导致值略低于 3.0。我不明白的是,与直接转换公式相比,为什么将下面的计算结果放入 double 并将其转换为左值然后将其转换为 unsigned int 会改变结果。以下代码显示了我的测试用例,它在我的 32 位 debian wheezy 机器上反复失败,但在我的 64 位 debian wheezy 机器上反复通过。
#include <cmath>
#include "assert.h"
int main () {
int n = 8;
unsigned int i =
static_cast<unsigned int>(std::log(static_cast<double>(n)) /
std::log(static_cast<double>(2)));
double d =
std::log(static_cast<double>(n)) / std::log(static_cast<double>(2));
unsigned int j = static_cast<unsigned int> (d);
assert (i == j);
}
我也知道我可以使用位移来以更可预测的方式得出我的结果。我很好奇为什么将导致操作的双精度数与将该值粘贴到堆栈上的双精度数并将双精度数投射到堆栈上有何不同。
【问题讨论】:
-
x87 内部使用 80 位算法。许多编译器在针对 x87 时,只是假装那些额外的位不存在。 x87 上的这种丑陋是常见的结果。告诉编译器使用 SSE 而不是 x87,例如
-mfpmath=sse。 -
与@tmyklebu 的评论相吻合:32 位 x86 系统的工具链通常默认以 x87 FPU 为目标进行浮点计算,而 64 位系统的工具链通常默认为使用 SSE。超精度、双舍入等的组合会导致您在此处观察到的那种效果。
标签: c++ floating-point double floating-accuracy