在这种情况下,是否有理由将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,除非我不理解强制转换和硬分配之间的某些区别。
答案 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...
。