将双重类型传递给ceil会导致GCC中不同优化级别的值不同

bgo*_*odr 3 c c++ math logarithm compiler-optimization

下面,result1和result2变量值报告不同的值,具体取决于您是使用-g还是使用-O在GCC 4.2.1和GCC 3.2.0上编译代码(我还没有尝试过更新的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;
Run Code Online (Sandbox Code Playgroud)

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

这似乎与编译器完成优化的方式不同,或者内部与IEEE浮点表示有关,但我很好奇这种差异究竟是如何发生的.我希望尽可能避免看汇编程序.

以上是用C++编译的,但我认为如果使用printfs将其转换为ANSI-C代码,则会保持相同.

上述差异发生在32位Linux上,但不适用于64位Linux.

谢谢bg

Dre*_*ins 6

在x86上,在进行优化的情况下,子表达式的结果在用作较大表达式的一部分之前不一定存储在64位内存位置.

因为x86的标准浮点寄存器是80位,这意味着在这种情况下,可以获得额外的精度.如果你然后将那个特别精确的值除以(或乘以)另一个,那么增加的精度的影响可以放大到肉眼可以感知的程度.

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

如果你真的在乎,你可以使用g ++标志来解决这个问题.