2012-09-22 35 views
1

我正在寫一個使用浮點數的紅寶石程序。我在精確度方面遇到了麻煩。例如在紅寶石浮法精度

1.9.3p194 :013 > 113.0 * 0.01 
# => 1.1300000000000001 

,因此

1.9.3p194 :018 > 113 * 0.01 == 1.13 
# => false 

這也正是那種計算我的應用程序需要得到正確的。

這是預期嗎?我應該如何處理這個問題?

+0

請記住,如果你想數錢,然後使用整數,而不是浮動。這是順便說一句。 – Hauleth

+0

感謝您的順便說一句。這不是金錢,價值是計算的結果,所以它們不限於離散的增量。 – mattfitzgerald

回答

4

這是浮點數的固有限制(甚至0.01沒有精確的二進制浮點表示)。您可以使用Aleksey提供的技術,或者,如果您想要完美的精度,請使用Ruby中捆綁的BigDecimal類。這是更詳細和更慢,但它會給出正確的結果:

require 'bigdecimal' 
=> true 
1.9.3p194 :003 > BigDecimal.new("113") * BigDecimal("0.01") 
=> #<BigDecimal:26cefd8,'0.113E1',18(36)> 
1.9.3p194 :004 > BigDecimal.new("113") * BigDecimal("0.01") == BigDecimal("1.13") 
=> true 
+0

這看起來很像。我會遭受性能和代碼優雅的打擊。 – mattfitzgerald

+0

使用'Rational'也是一種可能。 –

+0

您可以隨時創建一個實用程序類/函數來節省自己的額外編碼。就像'Money.add(a,b)'封裝了'BigDecimal'樣板文件。這就是我在我的項目中所做的事情,它對代碼的可讀性有很大的幫助。 – dimitarvp

2

在使用float計算時,您應該使用sigma方法 - 它意味着不要比較兩個值,但比較它們的絕對差值與一個非常小的值 - 例如1e-10。

((113 * 0.01) - 1.13).abs<1e-10 
+0

謝謝。這告訴我,我可能不應該在這裏使用Float。 – mattfitzgerald