2017-02-21 85 views
-2

我已經看遍了:Why can't decimal numbers be represented exactly in binary?Why Are Floating Point Numbers Inaccurate?紅寶石四捨五入和十進制數的格式

我的問題是,當我圓和格式浮動使用紅寶石點數,結果仍然不是做數學的結果不同的買手。下面是這樣一個例子:

編輯2

[28] pry(main)> ##################################### 
[29] pry(main)> # test one 
[30] pry(main)> ##################################### 
[31] pry(main)> foo = (6.0135 * (650000/1000)) 
      => 3908.7749999999996 
[32] pry(main)> foo = '%.2f' % foo.round(2) 
      => "3908.77" 
[33] pry(main)> # should be 3908.78 

[36] pry(main)> ##################################### 
[37] pry(main)> # test two 
[38] pry(main)> ##################################### 
[39] pry(main)> foo = 650000/1000 
      => 650 
[40] pry(main)> foo = foo * 6.0135 
      => 3908.7749999999996 
[41] pry(main)> foo = '%.2f' % foo.round(2) # should be 3908.78 
      => "3908.77" 

[44] pry(main)> ##################################### 
[45] pry(main)> # test three 
[46] pry(main)> ##################################### 
[47] pry(main)> foo = 650000/1000 
      => 650 
[48] pry(main)> foo = foo * 6.0135 
      => 3908.7749999999996 
[49] pry(main)> foo = foo.round(2) # should be 3908.78 
=> 3908.77 

[52] pry(main)> ##################################### 
[53] pry(main)> # test four - The result of test four is expected 
[54] pry(main)> ##################################### 
[55] pry(main)> foo = 650000/1000 
      => 650 
[56] pry(main)> foo = foo * 6.0135 
      => 3908.7749999999996 
[57] pry(main)> foo = '%.2f' % foo 
      => "3908.77" 

[58] pry(main)> ##################################### 
[59] pry(main)> # test five 
[60] pry(main)> ##################################### 
[61] pry(main)> foo = 650000/1000 
      => 650 
[62] pry(main)> foo = foo * 6.0135 
      => 3908.7749999999996 
[63] pry(main)> foo = foo.round(5) 
      => 3908.775 

測試1:這是正常的公式我在庫,是給我的問題,請使用。

測試2:在這裏,我的想法是,也許在做一個分配這兩個操作是造成一些問題

測試3:嗯,因爲'%.2f' %已經知道導致它截斷一些事情的四捨五入問題,也許這就是的問題。

測試4:由於'%.2f' %不是問題,所以.round(2)可能導致問題。

編輯2: 測試5:如果我展開一輪在看我得到一個數字,我可以(即24(2)再次證明數。)工作在數字。但是,這似乎是一個有限的案例,而不是一般

工作的一個不可思議的解決方案我真的不關心浮點數是不準確的。我的問題是我如何正確舍入這個數字,以便我得到正確的答案(如果你手動執行操作,你會得到答案)。

另外一般情況下,是否有一個最佳做法舍入來糾正劑量點錯誤?我知道它是用兩個整數來表示浮點數,但這似乎很麻煩。

謝謝。

編輯1

如果您使用的.round(5)代替.round(2)比較它的答案應該是什麼的時候,你會得到一個更合理的答案。增加本輪內線的數量是否有任何缺點?

+0

爲什麼downvote? –

+1

這一輪是正確的。 3908.77499999 ..將始終爲3908.77,因爲它確實小於3908.775。你總是圍繞總價值,你不開始在最後一個數字輪,然後出去...... –

+0

除了實際的答案應該是3908.78的事實。如果你使用'.round(5)',你會得到3908.78 –

回答

3

round按預期工作。你得到錯誤的結果,因爲你的輸入已經有缺陷。浮點數6.0135居然是:

6.01349999999999962341235004714690148830413818359375 

通過650乘以這個數字使錯誤更糟。你得到的結果比對3908.78接近3908.77

foo = 6.0135 * 650 
#=> 3908.7749999999996 

(foo - 3908.77).abs 
#=> 0.004999999999654392 

(foo - 3908.78).abs 
#=> 0.005000000000563887 

爲了得到正確的結果,你可以使用這樣的事情:

foo = (6.0135 * 10000).round * 0.065 
#=> 3908.775 

foo.round(2) 
#=> 3908.78 

或者你可以使用BigDecimal避免浮點錯誤首先:

require 'bigdecimal' 
foo = BigDecimal('6.0135') * 650 
foo.to_s('F') 
#=> "3908.775" 

foo.round(2).to_s('F') 
#=> "3908.78" 
+0

謝謝。除了一些表現受到影響之外,是否還有大的退步?我打算每次請求25次做這種數學計算,這種改變對請求的執行有多大影響? –

+1

@alex_milhouse Rails中的請求 - 響應循環並不那麼輕量級。如果25個計算會顯着影響它,我會感到驚訝。 – Stefan

+0

太棒了。謝謝,這正是我所需要的。 –

0

'%.2f' % - 截斷的數量和不能正確

.round(2)輪 - 看起來並不足夠小數回正確輪。所以如果你在大於2的數字內捨去的問題沒有了。

編輯1

有5種方法根據IEEE把一個數字:

  1. 到最近,領帶甚至
  2. 到最近,領帶從零
  3. 遠朝向0
  4. 朝+∞
  5. 朝-∞

在這種情況下,它不是我如何四捨五入,而是關於小數點後需要考慮的位數。通常一個人需要擔心精度。由於此錯誤是由計算機創建的,因此我認爲增加被認爲是小數點後的值的數量會更好,更準確。

+1

分裂人格? –

+1

我認爲你需要通過引用IEEE浮點標準來證明這些陳述的合理性,然後才能作爲答案。 –

+0

是啊@ muistooshort和lukasz我實際上有關於如何「解決」這個問題的第二個想法。雖然這給了我這個特定情況下我想要的答案。這樣做是否還有其他問題。 –

0

我測試了這一切對我的Rails控制檯,並不能看到任何奇怪的行爲:

>> foo = 650000/1000 
=> 650 
>> foo = foo * 6.0135 
=> 3908.7749999999996 
>> foo.round(2) 
=> 3908.77 
>> foo.round(3) 
=> 3908.775 
>> foo.round(5) 
=> 3908.775 
>> afoo = '%.2f' % foo 
=> "3908.77" 
>> afoo = '%.5f' % foo 
=> "3908.77500" 

3908.7749999999996比3908.775小,如果你使用.round(2)將四捨五入至3908.77。 。(5)3908.775的預期結果,也可以在谷歌計算器中複製。你爲什麼認爲這應該是錯誤的?我真的很想明白這一點。