我发现了一个有趣的案例,相同的C ++代码会在不同的系统上产生不同的结果。
#include <cstdio>
int main()
{
int a=20, b=14;
if(a*1.0/b*(a+1)/(b+1)==2) printf("YES!");
else printf("NO!");
}
使用GCC 4.6.3在Ubuntu Linux 12.04上编译,输出 YES!
使用GCC 4.6.2在Windows 7上编译,输出 NO!
但是,使用:
double c = a*1.0/b*(a+1)/(b+1);
if (c==2) printf("YES!");
...
将在两台计算机上返回 YES!。
出现这种差异的任何想法?这是由编译器版本不匹配造成的(路径级版本号应该不重要)?为什么它在Windows机器上实际输出 NO!,而这种情况显然是正确的?
答案 0 :(得分:14)
因为您正在对浮点类型进行相等比较,通常不应该依赖于机器之间(或从编译器到编译器等)的特定位精确行为。
可能的原因包括编译器选择何时从宽(80位)浮点寄存器中移出浮点结果(语言标准和IEEE-754浮点标准都没有强加任何特定要求,AFAIK)
答案 1 :(得分:12)
这只是猜测,您需要查看编译器的汇编输出才能确定。
一个编译器可能会将中间结果存入浮点寄存器,而另一个编译器将结果写入存储器,将其从80位舍入到64位。也可能是使用SSE而另一个不使用。
答案 2 :(得分:2)
这是因为浮点运算,请尝试使用epsilon比较:
#define EPSILON_EQUAL(a,b) ( fabs((a)-(b)) < (0.0001f) )
float f = a*1.0/b*(a+1)/(b+1);
if(EPSILON_EQUAL(f,2.0f)) printf("YES!");
答案 3 :(得分:1)
因为由于精度问题而比较浮点数是不正确的。
在数学2/3 =(0.6666666 .....到无穷大)//小学数学:)没有问题。
在计算中,此计算在浮点单元上执行(类似于CPU,但专用于浮点计算)。现在这个浮点单元(FPU)可能会给你一个非常接近你的实际答案的数字,但它们并不完全相同。因为它会截断结果。整个字段专用于浮点运算。总之,在比较中永远不要使用浮点数,因为你可能会得到相互矛盾的结果。
答案 4 :(得分:0)