我认为这是一个相当基本的问题,但我不知道为什么这两段代码会给出不同的结果。 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相同的结果。我在两者上使用默认的编译器设置。
答案 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
,它被迫做两个分裂。