为什么我的浮动除以0.00390625?

时间:2011-04-02 13:29:59

标签: c

float a=67107842,b=512;
float c=a/b;
printf("%lf\n",c);

为什么c 131070.000000而不是正确值131070.00390625?

3 个答案:

答案 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位有效数字。

请注意,在某些编译器上,doublelong double之间没有区别,甚至根本不支持long double

一种解决方案是使用任意精度的数值库,或者使用十进制浮点库而不是内置的二进制浮点支持。十进制浮点本质上不是更精确(尽管这些库通常支持更大,更精确的类型),但是不会显示在显示二进制浮点值的十进制表示时出现的假象。十进制浮点也可能要慢得多,因为它通常不是在硬件中实现的。

相关问题