2012-12-03 52 views
1

我都發生在一個Grails項目這個奇怪的劃分錯誤(但我認爲Grails的關係不大吧,是一個Groovy或Java的問題,我認爲):奇怪的浮動劃分結果

如果在常規控制檯我跑這個

float money = -1.30 
float r = 0.01 

println ((money/r).class.name) 
println ((money/r).floatValue()) 
println ((money/r).toString()) 

我得到這個輸出

java.lang.Double 
-130.0 
-129.99999813735482 

在常規浮動師給我一個雙人間,這是正確的,但 爲什麼雙的toString()給我一個很奇怪的值「-129.99999813735482」和 不正確的「-130.0」?

+3

[這](HTTP ://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html)可能會讓你感興趣 – Pshemo

+0

漂浮和雙打在某種程度上是不準確的。所以我的猜測是,'-130.0'是某種類似的近似值,'-129.99999813735482'是實際值。 –

+1

@Andrew Thompson:一般而言,如果可能的話,它應該被聲明爲十進制類型,如Java中的BigDecimal。 –

回答

4

正如大家所說,doublefloat對於您要做的事情不夠精確。

一種解決方法是不使用float作爲對象類型,然後執行:

def money = -1.30 
def r = 0.01 

println ((money/r).class.name) 
println ((money/r).floatValue()) 
println ((money/r).toString()) 

正如你所看到的,Groovy uses BigDecimal,這意味着輸出是:

java.math.BigDecimal 
-130.0 
-130 
+0

「double」和「float」不夠精確的說法很有趣。爲了正確得到準確的結果,需要多少位「加倍」? –

+0

無限多; 「0.01」不能完全表示爲二進制浮點數。 –

6

Floating-Point Guide

爲什麼我的數字,像0.1 + 0.2加起來一個漂亮的圓0.3, 而是我得到一個怪異的結果像0.30000000000000004?

由於內部計算機使用格式(二進制浮點數) ,因此無法準確表示數字,如0.1,0.2或0.3。

當代碼被編譯或解釋時,您的「0.1」已經被 舍入到該格式的最接近的數字,即使在計算髮生之前,這也會導致一個小的舍入誤差。

具體而言,float均不能準確表示1.3和0.01。

+0

是的,即使'System.out.println(1.3f)'顯示爲「1.3」,你可以用String.format(「%。16f」,1。3f)':'「1,2999999523162842」'並且根本看不到'1.3'。 – Esailija

1

通過執行floatValue,您正在限制該值的精確度。所以JVM做了四捨五入,你會得到不同的價值。

在你說「但130.0應該是計算的值,因爲它是正確的」請記住,計算機使用二進制格式來表示十進制數,這會導致舍入誤差與分數(嘗試代表0.3理解爲什麼)。

+0

在調用floatValue()之前,該值已經不準確:這會使情況變得更糟。 – EJP