2016-10-05 31 views
4

我需要做一些座標計算,並且碰到這個(至少對我來說)怪異的行爲 。 有人可以解釋爲什麼會發生這種情況嗎?爲什麼Ruby在計算mod時添加精度/數字?

$ long 
=> 49.0126760222489 
$ long % long.floor 
=> 0.012676022248896857 

我期待的最後一行來評價剛剛期後的數字,從long,而是有一個額外的6857上漲到年底。

爲什麼添加數字?

信息從哪裏來?

+0

你是怎麼計算long值的? – sokkyoku

+0

它來自數據庫 – Flip

+0

你正在使用哪個版本的Ruby? – quetzalcoatl

回答

2

我想我們只是看到浮動的不確定性。參見0.0126760222489 % 1.01.0126760222489 % 1.0。你會認爲結果應該是一樣的,但不是 - IEEE754漂浮/雙打併不能保證完美的結果,默認情況下這些在Ruby中用於存儲浮點值。

它甚至有點出in the docs

6543.21.modulo(137)  #=> 104.21 
6543.21.modulo(137.24) #=> 92.9299999999996 

你可以看到第二個結果有一個小錯誤。其實,關於Ruby 2.3.1我跑第一線,並得到:

pry(main)> 6543.21.modulo(137) 
=> 104.21000000000004 

它不一定與模數,而不是總是可見:

[30] pry(main)> 10.0126760222489 - 0.0 
=> 10.0126760222489 
[31] pry(main)> 10.0126760222489 - 1.0 
=> 9.0126760222489 
[32] pry(main)> 10.0126760222489 - 2.0 
=> 8.0126760222489 
[33] pry(main)> 10.0126760222489 - 3.0 
=> 7.0126760222489 
[34] pry(main)> 10.0126760222489 - 4.0 
=> 6.0126760222489 
[35] pry(main)> 10.0126760222489 - 5.0 
=> 5.0126760222489 
[36] pry(main)> 10.0126760222489 - 6.0 
=> 4.0126760222489 
[37] pry(main)> 10.0126760222489 - 7.0 
=> 3.0126760222489004 

使用標準的每一種軟件需要浮動以解決這些小錯誤。如果你不能處理,由於某種原因,那麼你可以使用bigdecimal(應該已經包含在你的Ruby),定點,或一些類似的數字圖書館

require 'bigdecimal' 

BigDecimal('6543.21').modulo(137).to_s 
=> "0.10421E3" 

BigDecimal('6543.21').modulo(137).to_f 
=> 104.21 

請記住,「BigDecimal的」可能會比較慢並可能使用更多的內存。

+0

太好了,謝謝您回答,儘管事先已經問過(並回答過) – Flip

3

它似乎沒有任何使用Ruby本身,而是:

浮點數,一般從這種類型的舍入誤差的痛苦,因爲他們僅限於字節x個,並,一般來說,不能完美存儲十進制數。

Documentation

從上面一個的文檔還可以得到幾個選項周圍的原生漂浮行爲得到。以上文檔可以被認爲是官方文檔,因爲它是由ruby-doc.org提供的。

+3

這不是一個「更精確」的結果,這是*更少*精確的結果。如果將「0000」加到最後,加上'6857'只會導致結果*錯誤*。 – meagar

+0

轉換'long.floor' Fixnum值似乎與我無關,因爲'long'本身已經是浮點。我發現浮動%fixnum沒有帶來浮動的驚喜。我想我們只是看到浮動的不確定性。請參閱「0.0126760222489%1.0」和「1.0126760222489%1.0」。 – quetzalcoatl