我正在寫一個使用浮點數的紅寶石程序。我在精確度方面遇到了麻煩。例如在紅寶石浮法精度
1.9.3p194 :013 > 113.0 * 0.01
# => 1.1300000000000001
,因此
1.9.3p194 :018 > 113 * 0.01 == 1.13
# => false
這也正是那種計算我的應用程序需要得到正確的。
這是預期嗎?我應該如何處理這個問題?
我正在寫一個使用浮點數的紅寶石程序。我在精確度方面遇到了麻煩。例如在紅寶石浮法精度
1.9.3p194 :013 > 113.0 * 0.01
# => 1.1300000000000001
,因此
1.9.3p194 :018 > 113 * 0.01 == 1.13
# => false
這也正是那種計算我的應用程序需要得到正確的。
這是預期嗎?我應該如何處理這個問題?
這是浮點數的固有限制(甚至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
這看起來很像。我會遭受性能和代碼優雅的打擊。 – mattfitzgerald
使用'Rational'也是一種可能。 –
您可以隨時創建一個實用程序類/函數來節省自己的額外編碼。就像'Money.add(a,b)'封裝了'BigDecimal'樣板文件。這就是我在我的項目中所做的事情,它對代碼的可讀性有很大的幫助。 – dimitarvp
在使用float計算時,您應該使用sigma方法 - 它意味着不要比較兩個值,但比較它們的絕對差值與一個非常小的值 - 例如1e-10。
((113 * 0.01) - 1.13).abs<1e-10
謝謝。這告訴我,我可能不應該在這裏使用Float。 – mattfitzgerald
請記住,如果你想數錢,然後使用整數,而不是浮動。這是順便說一句。 – Hauleth
感謝您的順便說一句。這不是金錢,價值是計算的結果,所以它們不限於離散的增量。 – mattfitzgerald