问题的症结在于0.41
IEEE 754 64 位二进制浮点不能完全表示。实际值(只有足够的精度来显示相关部分)是0.409999999999999975575...
, 而100
可以精确表示。将这些相乘应该得到40.9999999999999975575...
,这又不太具有代表性。在舍入模式接近最接近、零或负无穷大的可能情况下,应将其舍入为40.9999999999999964...
。当转换为 int 时,将四舍五入为40
.
然而,允许编译器以更高的精度进行计算,特别是可以用c
计算值的直接存储来代替赋值中的乘法。
编辑:我误算了小于 41 的最大可表示数,正确的值大约是40.99999999999999289...
. 正如 Eric Postpischil 和 Daniel Fischer 都正确指出的那样,即使是作为双精度计算的值也应该四舍五入,41
除非舍入模式接近零或负无穷大。你知道什么是四舍五入模式吗?正如此代码示例所示,它有所不同:
#include <stdio.h>
#include <fenv.h>
#pragma STDC FENV_ACCESS ON
int main(void)
{
int roundMode = fegetround( );
volatile double d1;
volatile double d2;
volatile double result;
volatile int rounded;
fesetround(FE_TONEAREST);
d1 = 0.41;
d2 = 100;
result = d1 * d2;
rounded = result;
printf("nearest rounded=%i\n", rounded);
fesetround(FE_TOWARDZERO);
d1 = 0.41;
d2 = 100;
result = d1 * d2;
rounded = result;
printf("zero rounded=%i\n", rounded);
fesetround(roundMode);
return 0;
}
输出:
nearest rounded=41
zero rounded=40