float a=67107842,b=512;
float c=a/b;
printf("%lf\n",c);
为什么c
131070.000000而不是正确值131070.00390625?
答案 0 :(得分:9)
您的编译器的float
类型可能使用32位IEEE 754单精度格式。
67107842是一个26位二进制数:
11111111111111110000000010
单精度格式表示大多数数字为1.x
乘以2的一些(正或负)幂,其中23位存储在二进制位置之后,隐含前导1.
(非常小的数字是一个例外)。
但67107842在二进制位置后需要24位(表示为1.111111111111111000000001
乘以2 25 )。由于只有存储23位的空间,最终的1
会丢失。因此a
中的值在这种情况下是错误的,而不是除法 - a
实际上包含67107840(11111111111111110000000000
),正好是131070 * 512。
如果您同时打印a
,也可以看到这一点:
printf("%lf %lf %lf\n", a, b, c);
给出
67107840.000000 512.000000 131070.000000
答案 1 :(得分:7)
尝试将a和c更改为“double”类型,而不是浮动。这将为您提供更好的精度/准确度。 (浮动大约有6个左右的有效数字;双打的数字是两倍以上。)
答案 2 :(得分:0)
float
通常使用32位IEEE-754单精度表示,仅适用于大约6位有效小数。 double
适用于15,支持80位long double
可获得20位有效数字。
请注意,在某些编译器上,double
和long double
之间没有区别,甚至根本不支持long double
。
一种解决方案是使用任意精度的数值库,或者使用十进制浮点库而不是内置的二进制浮点支持。十进制浮点本质上不是更精确(尽管这些库通常支持更大,更精确的类型),但是不会显示在显示二进制浮点值的十进制表示时出现的假象。十进制浮点也可能要慢得多,因为它通常不是在硬件中实现的。