Ruby BigDecimal Round: это ошибка? - PullRequest
9 голосов
/ 13 января 2010

При написании теста со значением, которое представляется в виде BigDecimal, я столкнулся с чем-то странным и решил покопаться в нем. Вкратце, «0,00009» при округлении до двух десятичных знаков возвращается как 0,01 вместо 0,00. В самом деле. Вот мой скрипт / захват консоли:

>> bp = BigDecimal('0.09')
=> #<BigDecimal:210fe08,'0.9E-1',4(8)>
>> bp.round(2,BigDecimal::ROUND_HALF_DOWN).to_f
=> 0.09
>> bp = BigDecimal('0.009')
=> #<BigDecimal:210bcf4,'0.9E-2',4(8)>
>> bp.round(2,BigDecimal::ROUND_HALF_DOWN).to_f
=> 0.01
>> bp = BigDecimal('0.0009')
=> #<BigDecimal:2107a8c,'0.9E-3',4(12)>
>> bp.round(2,BigDecimal::ROUND_HALF_DOWN).to_f
=> 0.0
>> bp = BigDecimal('0.00009')
=> #<BigDecimal:2103428,'0.9E-4',4(12)>
>> bp.round(2,BigDecimal::ROUND_HALF_DOWN).to_f
=> 0.01
>> bp = BigDecimal('0.000009')
=> #<BigDecimal:20ff0f8,'0.9E-5',4(12)>
>> bp.round(2,BigDecimal::ROUND_HALF_DOWN).to_f
=> 0.0

О, и я получаю те же результаты, если я использую режим по умолчанию, например:

>> bd = BigDecimal('0.00009')
=> #<BigDecimal:2152ed8,'0.9E-4',4(12)>
>> bd.round(2).to_f
=> 0.01

Вот мои версии:

ruby 1.8.6 (2008-03-03 patchlevel 114) [i686-darwin9.2.2]
Rails 2.3.4

Кто-нибудь видел что-нибудь подобное?

Ответы [ 2 ]

6 голосов
/ 13 января 2010

Нет, никогда раньше не видел, и это определенно похоже на ошибку.0.00009 округленное до двух знаков после запятой определенно должно быть 0.00.

ROUND_HALF_DOWN не должно изменять поведение, поскольку вы не имеете дело со значениями средней точки.

Этоссылка содержит более подробную информацию.

Кажется, это ошибка в уровне 1.8, которая была исправлена ​​в 1.9.Это немного странно, поскольку кажется, что оно влияет только на числа с четным числом нулей перед первой ненулевой цифрой и только если эта цифра равна 5 или больше.

Похоже, что точно Ваша проблема основана на предоставленных данных.

0 голосов
/ 31 марта 2010

Думаю, это тоже ошибка, но мне интересно узнать, как .to_f отображать результат. С BigDecimal вы должны использовать .to_s ('F') вместо этого, так как я думаю, у вас есть причина использовать BigDecimal вместо Floats.

...