Точность округления числа-до-валюты неправильная - PullRequest
2 голосов
/ 22 ноября 2010

Мне очень любопытно, почему в Ruby непоследовательна рендеринг десятичной дроби с точностью 2.

Например:

helper.number_to_currency 9.995

=> "$ 9,99"

пока

helper.number_to_currency 10.995

=> "$ 11,00" ... это должно быть "$ 10,99"?

Ответы [ 2 ]

5 голосов
/ 15 декабря 2010

Это ошибка точности с плавающей запятой. Я, вероятно, отправлю патч, чтобы исправить это, потому что я использую 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

Предоставленное вами число умножается на 100, прежде чем оно конвертируется в BigDecimal. Посмотрите на этот простой сеанс IRB:

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

Очевидно, что это число округляется до 999, затем оно будет разделено на 100, что даст вам 9,99.

Единственный способ обойти это, о котором я сейчас могу подумать, - это сделать свое собственное округление до того, как вы введете число.

0 голосов
/ 22 ноября 2010

Похоже, что используется правило "округлить до половины".

Таким образом, «1,5» округляется до ближайшего нечетного числа (1), а 2,5 округляется до ближайшего нечетного числа (3).

Для округления случайно распределенного набора чисел эта форма округления будет давать наименьшую разницу между суммой необоснованных чисел и суммой округленных чисел.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...