我很困惑。我没有解释为什么这个测试在使用double
数据类型时通过但在使用数据类型时失败float
。考虑以下代码片段。
float total = 0.00;
for ( int i = 0; i < 100; i++ ) total += 0.01;
人们预计total
为 1.00,但它等于 0.99。为什么会这样?我用 GCC 和 clang 编译,两个编译器都有相同的结果。
尝试这个:
#include <stdio.h>
int main(){
float total = 0.00;
int i;
for (i = 0; i < 100; i++)
total += 0.01;
printf("%f\n", total);
if (total == 1.0)
puts("Precise");
else
puts("Rounded");
}
至少在大多数机器上,你会得到“圆角”的输出。换句话说,结果恰好足够接近,以至于当它被打印出来时,它是四舍五入的,所以它看起来正好是 1.00,但实际上不是。更改total
为 a double
,您仍然会得到相同的结果。
十进制 0.01 的值表示为系列:a1*(1/2) + a2*(1/2)^2 + a3*(1/2)^4 + 等。其中aN
是零或一。
我留给您计算 a1、a2 的具体值以及需要多少小数位 ( aN
)。在某些情况下,小数部分不能由 (1/2)^n 值的有限系列表示。
要使这个系列在十进制中求和为 0.01,需要aN
超出存储在浮点数中的位数(完整的位字减去符号和指数的位数)。但是由于 double 具有更多位,因此可以/可能/可能(您进行计算)精确定义 0.01 十进制。