2011-04-02 69 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

一個解決方案是使用任意精度的數字庫,或者使用十進制浮點庫而不是內置的二進制浮點支持。十進制浮點本質上並不精確(儘管通常這種類型的庫支持更大,更精確的類型),但不會顯示在顯示二進制浮點值的十進制表示時發生的人爲影響。十進制浮點數也可能要慢得多,因爲它通常不是用硬件實現的。

相關問題