2013-06-08 2 views
2

Я получаю странное поведение с BigDecimal в рубине. Почему это печатает false?BigDecimal теряет точность после умножения

require 'bigdecimal' 

a = BigDecimal.new('100') 
b = BigDecimal.new('5.1') 
c = a/b 
puts c * b == a #false 
+1

Это действительно «BigDecimal теряет точность после деления». –

ответ

2

Это нормальное поведение, и вовсе не странно.

BigDecimal не гарантирует бесконечную точность, это позволяет указать произвольно точность, что не то же самое. Значение 100/5.1 не может быть выражено с полной точностью, используя внутреннее представление с плавающей запятой. Неважно, сколько бит используется.

«Большой рациональный» подход мог бы достичь этого - но не дал бы вам доступа к некоторым функциям, например. квадратные корни.

См http://ruby-doc.org/core-1.9.3/Rational.html

# require 'rational' necessary only in Ruby 1.8 
a = 100.to_r 
b = '5.1'.to_r 
c = a/b 
c * b == a 
# => true 
+0

«Требовать« рациональный »в Ruby> 1.9 не требуется. – steenslag

3

BigDecimal не претендует иметь бесконечную точность, она просто обеспечивает поддержку точностей вне нормального с плавающей точкой в ​​диапазоне:

BigDecimal обеспечивает такую ​​же поддержку для очень больших или очень точные числа с плавающей запятой.

Но значения BigDecimal еще имеют конечное число значащих цифр, следовательно, в precs method:

precs

возвращает массив из двух целых значений.

Первое значение - это текущее количество значащих цифр в BigDecimal. Второе значение - максимальное количество значащих цифр для BigDecimal.

Вы можете видеть, что вещи начинают идти наперекосяк, если вы посмотрите на c:

>> c.to_s 
=> "0.19607843137254901960784313725E2" 

Это хорошее чистое рациональное число, но BigDecimal не знает, что он все еще застряли видя c как конечная строка цифр.

Если вы используете Rational вместо этого, вы получите результаты вы ожидаете:

>> a = Rational(100) 
>> b = Rational(51, 10) 
>> c * b == a 
=> true 

Конечно, это обман, только если вы работаете с рациональными числами, так что ничего фантазии (например, корни или тригонометрия) выходит за пределы.

Смежные вопросы