开发者

number_to_currency rounding precision wrong

I am very curious why Ruby render decimal with precision 2 in开发者_运维知识库consistently.

For example:

helper.number_to_currency 9.995

=> "$9.99"

whilst

helper.number_to_currency 10.995

=> "$11.00"...should it be "$10.99"?


It is a floating point precision error. I will probably submit a patch to fix this because I'm using number_to_currency on my website too.

Here's what's happening in more detail:

number_to_currency ends up just calling number_with_precision to get the number correctly formatted. number_with_precision immediately converts the number to a Float. Essentially, it comes down to this line in the Rails code:

# 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

The number you provide is multiplied by 100 before it is converted to BigDecimal. Look at this simple irb session:

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

That number would obviously round down to 999, then it will be divided by 100 to give you 9.99.

The only workaround for this that I can think of for the moment is to do your own rounding before you pass in the number.


Looks like it is using "Round half to odd" rule.

So "1.5" gets rounded down to the nearest odd number (1) and 2.5 gets rounded up to the nearest odd number (3).

For a randomly distributed set of numbers to be rounded this form of rounding will consitently produce the smallest difference between the sum of unrounded numbers and the sum of rounded numbers.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜