我有以下代码:
#include <cstdio>
int main()
{
if ((1.0 + 0.1) != (1.0 + 0.1))
printf("not equal\n");
else
printf("equal\n");
return 0;
}
当使用 gcc(4.4、4.5 和 4.6)使用 O3 编译并本机运行(ubuntu 10.10)时,它会打印“等于”的预期结果。
但是,当按照上述方式编译并在虚拟机(ubuntu 10.10,virtualbox 映像)上运行相同的代码时,它会输出“不等于” - 这是设置 O3 和 O2 标志但未设置 O1 及以下的情况。当使用 clang(O3 和 O2)编译并在虚拟机上运行时,我得到了正确的结果。
我了解 1.1 无法使用 double 正确表示,并且我已阅读“每个计算机科学家应该了解的关于浮点运算的知识”,所以请不要指点我,这似乎是 GCC 所做的某种优化不知何故似乎在虚拟机中不起作用。
有任何想法吗?
注意:C++ 标准说在这种情况下类型提升是依赖于实现的,可能是 GCC 使用了更精确的内部表示,当应用不等式测试时它是正确的 - 由于额外的精度?
UPDATE1:对上述代码进行以下修改,现在会产生正确的结果。似乎在某些时候,无论出于何种原因,GCC 都会关闭浮点控制字。
#include <cstdio>
void set_dpfpu() { unsigned int mode = 0x27F; asm ("fldcw %0" : : "m" (*&mode));
int main()
{
set_dpfpu();
if ((1.0 + 0.1) != (1.0 + 0.1))
printf("not equal\n");
else
printf("equal\n");
return 0;
}
UPDATE2:对于那些询问代码的 const 表达式性质的人,我已将其更改如下,但在使用 GCC 编译时仍然失败。- 但我认为优化器也可能将以下内容转换为 const 表达式。
#include <cstdio>
void set_dpfpu() { unsigned int mode = 0x27F; asm ("fldcw %0" : : "m" (*&mode));
int main()
{
//set_dpfpu(); uncomment to make it work.
double d1 = 1.0;
double d2 = 1.0;
if ((d1 + 0.1) != (d2 + 0.1))
printf("not equal\n");
else
printf("equal\n");
return 0;
}
UPDATE3 解决方案:将 virtualbox 升级到版本 4.1.8r75467 解决了该问题。然而,他们仍然存在一个问题,那就是:为什么 clang 构建工作。