2010-11-22 10 views
2

なぜRubyが精度2で10進数を一貫してレンダリングするのか、非常に不思議です。例えばnumber_to_currency丸め精度が正しくない

helper.number_to_currency 9.995 

=> "$ 9.99"

helper.number_to_currency 10.995 

=> "$ 11.00" ながら...それは "$ 10.99" である必要がありますか?

+1

これは浮動小数点精度の問題である可能性があります。 – You

答えて

5

浮動小数点精度エラーです。自分のWebサイトでnumber_to_currencyも使用しているので、これを修正するためのパッチを提出する予定です。

は、ここでより詳細に何が起こっているかです:

number_to_currencyがちょうど正しく書式設定された数値を取得するにはnumber_with_precisionを呼び出してしまいます。 number_with_precisionはすぐに数値をフロートに変換します。基本的に、それはRailsのコードでこの行にダウンしています:

# File actionpack/lib/action_view/helpers/number_helper.rb, line 280 
rounded_number = BigDecimal.new((number * (10 ** precision)).to_s).round.to_f/10 ** precision 

あなたはそれがBigDecimalをに変換される前に100を乗じて提供数。この単純なのirbセッションを見てください:

irb(main):001:0> 9.995 * 100 
=> 999.4999999999999 

その数は明らかに、あなた9.99を与えるために100によって分割されます、999に切り捨てます。

私が現時点で考えることのできる唯一の回避策は、番号を渡す前に自分の丸めを行うことです。

+0

私はあなたがここで見ることができるパッチを提出しました: https://rails.lighthouseapp.com/projects/8994/tickets/6182-another-rounding-problem-in-number_with_precision – dontangg

-2

"奇数に丸める"ルールのように見えます。

したがって、「1.5」は最も近い奇数(1)に切り上げられ、2.5は最も近い奇数(3)に切り上げられます。

ランダムに分散された数値の丸めの場合、この丸めの形式は、丸められていない数値の合計と丸められた数値の合計の間で最小の差を確実に生成します。

関連する問題