为什么这两个简单的代码会给出不同的结果?

时间:2013-09-05 14:39:42

标签: c x86

我认为这是一个相当基本的问题,但我不知道为什么这两段代码会给出不同的结果。 Pentium处理变量Divider的方式与中间值(256.0 /(double)k)不同吗?

int j=64, k=20;  
double x, y, Divider;

Divider = 256.0 / (double)k;
x = (double)j / Divider - 5.0;
y = (double)j / ( 256.0 / (double)k ) - 5.0;

结果:     x = -2.77555756156289E-16     y = 0.0

作为参考,我使用的是Embarcadero的XE3 C ++ Builder,它提供与Builder 6相同的结果。我在两者上使用默认的编译器设置。

2 个答案:

答案 0 :(得分:2)

问题在于,当您不使用SSE指令时,编译器可能会选择使用本机387浮点单元进行中间计算,该单元使用80位值进行所有计算。

x的计算中,通过将中间值存储在Divisor中,可以强制将中间值截断为64位。然后下一个师使用已经舍入的除数;由于除法是以足够的精度完成的,因此结果与5.0略有不同。

y的计算中,除法以80位精度完成,因此结果更接近5.0(足够接近截断到64位使其为0)。

如果使用SSE(仅具有64位寄存器),或者强制编译器以64位精度执行所有计算,您还将获得两个0值。

答案 1 :(得分:0)

也许是优化器。在第二个

y = (double)j / ( 256.0 / (double)k )

在数学上相同
y = (double)j * (double)k / 256.0

这只能进行一次划分(巧合地划分得很清楚)并且可以减少舍入误差。

对于x,它被迫做两个分裂。