直接将双结果分配给int时的精度损失/舍入差异

时间:2015-01-30 19:52:06

标签: c math casting double precision

在这种情况下,是否有理由将double从int转换为预期执行:

double value = 45.33;
double multResult = (double) value*100.0; // assign to double
int convert = multResult;                 // assign to int
printf("convert = %d\n", convert);        // prints 4533 as expected

但不是在这种情况下:

double value = 45.33;
int multResultInt = (double) value*100.0;      // assign directly to int
printf("multResultInt = %d\n", multResultInt); // prints 4532??

在我看来应该没有区别。在第二种情况下,结果仍然首先存储为double,然后转换为int,除非我不理解强制转换和硬分配之间的某些区别。

2 个答案:

答案 0 :(得分:4)

两者之间确实没有区别,但是当涉及到浮点计算时,编译器习惯于获得一些自由。例如,编译器可以自由地使用更高精度来计算中间结果,但更高仍然意味着不同,因此结果可能会有所不同。

有些编译器提供的开关总是会降低额外的精度,并将所有中间结果转换为规定的浮点数(比如64位双精度数)。但是,这会使代码变慢。

具体而言,数字45.33不能用浮点值精确表示(当用二进制表示时,它是一个周期数,它需要无限数量的位)。当乘以100时,此值可能,您不会得到一个整数,但会非常接近(恰好在下方或上方)。

int转换或强制转换是使用截断来执行的,非常接近4533但非常接近4532,当上面的变为4533时;即使差异非常微小,请说1E-300

为避免出现问题,请务必考虑数字准确性问题。如果您的计算依赖于浮点数的精确值,那么您使用了错误的工具。

答案 1 :(得分:1)

@ 6502给了你理论,这里是如何通过实验来看待事物

double v = 45.33;
int x = v * 100.0;
printf("x=%d v=%.20lf v100=%.20lf\n", x, v, v * 100.0 );

在我的机器上,打印

x=4533 v=45.32999999999999829470 v100=4533.00000000000000000000

当编码为64位IEEE-754浮点数时,值45.33没有精确的表示。由于编码的精度有限,v的实际值略低于预期值。

那么为什么乘以100.0可以解决某些机器上的问题?一种可能性是乘法以80位精度完成,然后舍入以适合64位结果。当转换为64位时,80位数4532.999...将舍入为4533

在您的机器上,乘法显然是以64位精度完成的,我希望v100将打印为4532.999...