3

下面,result1 和 result2 变量值报告不同的值,具体取决于您是在 GCC 4.2.1 和 GCC 3.2.0 上使用 -g 还是使用 -O 编译代码(我还没有尝试过更新的 GCC 版本) :

double double_identity(double in_double)
{
    return in_double;
}

...

double result1 = ceil(log(32.0) / log(2.0));
std::cout << __FILE__ << ":" << __LINE__ << ":" << "result1==" << result1 << std::endl;

double result2 = ceil(double_identity(log(32.0) / log(2.0)));
std::cout << __FILE__ << ":" << __LINE__ << ":" << "result2==" << result2 << std::endl;

result1 和 result2 == 5 仅在使用 -g 编译时,但如果我使用 -OI 编译,则得到 result1 == 6 和 result2 == 5。

这似乎是编译器如何进行优化的差异,或者与内部的 IEEE 浮点表示有关,但我很好奇这种差异究竟是如何发生的。如果可能的话,我希望避免查看汇编程序。

上面是用 C++ 编译的,但我认为如果使用 printfs 将其转换为 ANSI-C 代码,情况也是如此。

上述差异发生在 32 位 Linux 上,但不在 64 位 Linux 上。

谢谢博主

4

1 回答 1

6

在 x86 上,通过优化,子表达式的结果在用作更大表达式的一部分之前不一定存储到 64 位内存位置。

因为 x86 的标准浮点寄存器是 80 位,这意味着在这种情况下,可以使用额外的精度。如果您然后将该特别精确的值除以(或乘以)另一个值,则提高精度的效果可以放大到肉眼可以感知的程度。

英特尔的 64 位处理器使用 SSE 寄存器进行浮点数学运算,而这些寄存器没有额外的精度。

如果您真的关心,您可以使用g++ 标志来解决此问题。

于 2010-07-24T05:26:39.423 回答