2014-03-28 26 views
-1

java中運行kmeans集羣時,數據點0.33和0.99之間的絕對差值顯示爲0.659999999而不是0.66。Abs(0.33-0.99)= 0.6599999999爲什麼?

這是爲什麼?

保存數據的兩個變量都是double類型,我使用的是Math.abs()函數。

我看到這樣的問題只有0.99。當使用其他值進行相減時,結果很好。

感謝所有幫助

+8

見[浮點運算:問題和限制]的 特徵(http://docs.python.org/3/tutorial/floatingpoint。 html) - 文章來自Python文檔,但問題是語言無關的。在許多情況下,二進制浮點數不能準確存儲十進制浮點數。 –

+0

這個視頻很好地解釋了這一點。 https://www.youtube.com/watch?v = PZRI1IfStY0 – dburner

+0

@Jakob:即使你的算盤(和你的手指+腳趾也)只有有限數量的位可用; -P – JensG

回答

3

浮點數據類型(浮點和雙精度)的丟失的主要因素不能在存儲器位來精確地表示。它們大約在內存中表示。

將無限多個實數擠壓成有限位數 需要近似表示法。雖然無限多個整數,但在大多數程序中,整數計算的結果可以以32位存儲。相比之下,給定任意固定位數,大多數使用實數的計算將產生不能使用那麼多位精確表示的數量。因此,浮點計算的結果必須經常按照 的順序進行四捨五入以適應其有限表示。此舍入誤差是浮點計算

What Every Computer Scientist Should Know About Floating-Point Arithmetic

+2

如果你不介意,你能解釋爲什麼'Math.abs(new Float(0.33-0.99))'返回'0.66'而不是? – DnR

1

雙打可能不準確,因爲它們存儲在內存中的方式。點擊此處瞭解詳情: https://en.wikipedia.org/wiki/Double-precision_floating-point_format

如果您需要確切的結果,你應該看看BigDecimal

+0

BigDecimal不比「double」更精確。它只適用於一組不同的數字。 –

+1

你可以支持這種說法嗎?因爲,據我所知,BigDecimal更準確。 從文檔:「當MathContext對象提供的精度設置爲0(例如,MathContext.UNLIMITED)時,算術運算是精確的,而算術方法不採用MathContext對象。」 –

+0

注:我沒有說這不是「更準確」。我說這是一組不同的數字,而不是「double」(「double」對於很多數字是精確的,如果你知道你在做什麼,就可以做很長的一系列精確的「雙」計算),而且「如果你需要一個確切的結果,你應該看看BigDecimal」是一個錯誤的描述。讓我這樣說:我想要1除以3的確切結果。對於這個基本操作來說,「查看BigDecimal」是浪費時間。它不會工作。 –

2

這是浮點數的行爲。他們不準確。

檢查: - What Every Computer Scientist Should Know About Floating-Point Arithmetic

也增加,浮點數使用二進制小數,而不是小數。如果你需要精確的十進制值,你應該使用java.math.BigDecimal

您可以檢查此answer以及更多的理由和細節:

浮點舍入誤差。 0.1不能被表示爲 準確在鹼-2作爲在鹼-10由於 5.