2010-03-11 92 views
18

(int)(33.46639 * 1000000)返回33466389爲什麼(int)(33.46639 * 1000000)返回33466389?

爲什麼會發生這種情況?

+0

你期望發生的? – SLaks 2010-03-11 01:54:26

+0

@Slaks:3346639,又名,正確的答案。 – 2010-03-11 01:56:04

+0

開始的好地方:http://docs.sun.com/source/806-3568/ncg_goldberg.html(每個計算機科學家應該瞭解浮點運算) – mjv 2010-03-11 01:57:04

回答

31

浮點數學並不完美。 What every programmer should know關於它。

浮點運算被許多人認爲是一個深奧的主題。這是相當令人驚訝的,因爲浮點在計算機系統中無處不在。幾乎每種語言都有一個浮點數據類型;從PC到超級計算機的計算機都有浮點加速器;大多數編譯器會被要求不時地編譯浮點算法;幾乎每個操作系統都必須響應浮點異常,例如溢出。本文提供了一個關於浮點的方面的教程,這些方面對計算機系統的設計者有直接的影響。它從浮點表示和舍入錯誤的背景開始,繼續討論IEEE浮點標準,並結合大量計算機構建者如何更好地支持浮點的例子。

...

擠壓無窮多的實數爲有限位數需要一個近似表示。雖然有無限多的整數,但在大多數程序中,整數計算的結果可以存儲在32位中。相反,給定任意固定的位數,大多數使用實數的計算都會產生無法使用多位來精確表示的數量。因此,浮點計算的結果必須經過四捨五入以適應其有限表示。該舍入誤差是浮點計算的特徵。

+1

的確,浮點運算既無處不在,也很複雜,但這並不能回答這個問題(除非您鏈接到一個有答案的80頁的論文)。 – 2010-03-11 02:00:45

+2

@亨利 - 重點在於鏈接文章的標題。 **每個**程序員都應該知道這一點,如果他們不這樣做,他們應該閱讀文章。 (好吧,也許不是所有的80頁...) – 2010-03-11 02:16:36

+9

+1:鏈接到一個80頁的文件,有答案的地方是標準anwser。這個問題 - 以某種形式 - 被頻繁地詢問。本文是*答案。問題都是重複的。我們不需要一再重複這些信息。 – 2010-03-11 02:25:56

5

雙精度不準確,所以在內部33.46639實際存儲爲33.466389

編輯:正如理查德說,它的浮點數據(以二進制存儲在一個有限的位集合),所以它不完全是) ...

+1

或33.4668885或其他「足夠接近」,取決於硬件。 – DaveE 2010-03-11 01:57:19

+1

嗯,以上都不是。它的基數爲2.大多數這樣的數字不能完全以10爲底數表示(不管怎樣,無需使用無限重複的數字序列,類似於基數10中的1/3必須表示爲0.33333 [inf]。) – 2010-03-11 02:02:37

+0

,不完全是......但比原來的更接近那個。 – 2010-03-11 02:06:11

-1

你有不同的結果的原因是,您使用的「

 
(int)(33.46639 * 1000000) returns 33466389 
^^^^^ 

的結果轉換爲一個類型的「廉政」的事實......這無論是圍捕或向下整數類型時,一起倍增,然後轉換爲'int'....不要依靠浮點足夠準確.... Skeet張貼在他的網站上的優秀介紹herehere ...

+0

演員陣容本身沒有任何損失。存在任意精度庫。 – 2010-03-11 01:57:59

+0

我想象他在問:「我的結果中有8個來自哪裏?」乘以1000000就像將小數點6位移到右邊,應該是「33466390」,但這不是他所得到的。你的答案是我最初想的,直到我再次讀到這個問題。 – Pwninstein 2010-03-11 01:59:48

+0

@Richard - 將'float'或'double'強制轉換爲'int'會丟棄小數部分,所以您確實會丟失信息。 – Seth 2010-03-11 02:32:50

1

如果你問它爲什麼沒有變成33466390,這是因爲doubles沒有無限精度,而且數字不能用二進制精確表示。

如果更換doubledecimal(int)(33.46639m * 1000000)),它等於33466390,因爲decimal s的在鹼計算10.

+0

像這些問題是浮點內在的問題,而不僅僅是二進制浮點。當然,十進制得到了33.46639 * 1000000的權利,但仍然有1/3 * 3!= 1和pow(sqrt(2),2)!= 2. – dan04 2010-03-11 02:33:12

+0

是的,但他的具體問題是由於二進制。 – SLaks 2010-03-11 02:40:59

2

其原因是33.46639將被表示爲一些比該數量稍少。

乘以1000000會給你33466389.99999999。

使用(int)進行類型轉換將僅返回整數部分(33466389)。

如果您想要「正確」的數字,請在類型轉換之前嘗試round()。

+4

哇! .....不不,不,不。如果你想要「正確的」答案,你不能使用浮點運算。 – 2010-03-11 02:08:40

+4

不可以。如果你想要「正確」的答案,你不能使用*二進制*浮點運算。使用使用十進制浮點運算的「decimal」類型,它將按照您的預期工作。 – Gabe 2010-03-11 02:13:58

+1

33.46639是「正確的」答案。問題是提問者沒有提出正確的問題。 – 2010-03-11 02:21:54

1

因爲33.46639不能準確地表示有限數量的二進制數字。 33.46639 * 1000000的實際結果是33466389.9999999962747097015380859375。演員將它截斷爲33466389.

+0

嘗試「不能準確表達在有限數量的小數二進制數字」 – 2010-03-11 07:15:42

3

這是1994年底的除夕夜。英特爾首席執行官安迪格羅夫(Andy Grove)出現了一個偉大的一年,奔騰處理器出現並受到重創。於是,他走進一家酒吧,點了一瓶Johnnie Walker綠色標籤。

酒保送達並說,「那將是20美元,先生。」

格羅夫在櫃檯上放了一張二十美元的鈔票,看了一會兒,說道:「保持變化。」

http://en.wikipedia.org/wiki/Pentium_FDIV_bug

+0

但是...這是一個整數... – Rawling 2014-06-11 08:37:00

相關問題