Я получаю странное поведение с BigDecimal
в рубине. Почему это печатает false?BigDecimal теряет точность после умножения
require 'bigdecimal'
a = BigDecimal.new('100')
b = BigDecimal.new('5.1')
c = a/b
puts c * b == a #false
Я получаю странное поведение с BigDecimal
в рубине. Почему это печатает false?BigDecimal теряет точность после умножения
require 'bigdecimal'
a = BigDecimal.new('100')
b = BigDecimal.new('5.1')
c = a/b
puts c * b == a #false
Это нормальное поведение, и вовсе не странно.
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
«Требовать« рациональный »в Ruby> 1.9 не требуется. – steenslag
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
Конечно, это обман, только если вы работаете с рациональными числами, так что ничего фантазии (например, корни или тригонометрия) выходит за пределы.
Это действительно «BigDecimal теряет точность после деления». –