2011-04-02 87 views
1
float a=67107842,b=512; 
float c=a/b; 
printf("%lf\n",c); 

为什么c 131070.000000而不是正确的值131070.00390625?为什么我的浮动除法0.00390625?

+0

浮点数字并不准确。 – driis 2011-04-02 13:36:08

+2

在阅读浮点数学之前,您应该阅读以下内容:http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html。 – 2011-04-02 13:49:42

+1

如果你没有足够的理由使用'float',那么总是比较喜欢'double'。一个足够好的理由**不是**,“因为它们更快”(大多是假的);或“因为他们更小”(大部分是真的); “或者因为double需要6个字符而浮动需要5个”。 – pmg 2011-04-02 13:58:27

回答

9

您的编译器的float类型可能使用32位IEEE 754单精度格式。

67107842是一个26比特的二进制数:

11111111111111110000000010 

单精度格式表示最数作为1.x通过两个一些(正或负)功率,其中23位被二进制后存储multipled与暗示的领先1.(非常小的数字是例外)。

但是67107842在二进制位之后将需要24位(将被表示为1.111111111111111000000001倍增2 )。由于只有23位存储空间,因此最后的1会丢失。因此,它是错在这种情况下a的价值,而不是分裂 - a实际上包含67107840(11111111111111110000000000),这正好是131070 * 512

你可以看到这一点,如果你打印a还有:

printf("%lf %lf %lf\n", a, b, c); 

给出

67107840.000000 512.000000 131070.000000 
+0

ideone的编译器使用像您所描述的'float':http://ideone.com/pA0My – pmg 2011-04-02 15:48:17

7

尝试更改a和c键入“double”,而不是float。这会给你更好的精度/准确性。 (浮点数大约有6位左右有效数字;双数有两倍以上)

0

float通常使用32位IEEE-754单精度表示,并且是良好的仅约6显著小数音响gures。 A double适用于15,支持80位long double可获得20位有效数字。

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

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