BigDecimal
Rubyで奇妙な動作をしています。なぜこれは間違っているのですか?
require 'bigdecimal'
a = BigDecimal.new('100')
b = BigDecimal.new('5.1')
c = a / b
puts c * b == a #false
BigDecimal
Rubyで奇妙な動作をしています。なぜこれは間違っているのですか?
require 'bigdecimal'
a = BigDecimal.new('100')
b = BigDecimal.new('5.1')
c = a / b
puts c * b == a #false
BigDecimal は、無限の精度があるとは主張していません。通常の浮動小数点範囲外の精度をサポートしているだけです。
BigDecimal
非常に大きなまたは非常に正確な浮動小数点数に対して同様のサポートを提供します。
ただし、 BigDecimal 値の有効桁数は有限であるため、precs
メソッドは次のようになります。
処方箋
2 つの整数値の配列を返します。
最初の値は、BigDecimal の現在の有効桁数です。2 番目の値は、BigDecimal の最大有効桁数です。
あなたが見ると、物事がうまくいかなくなっているのを見ることができますc
:
>> c.to_s
=> "0.19607843137254901960784313725E2"
これはきれいな有理数ですが、BigDecimal はそれを認識していませんc
。数字の有限文字列として表示されたままです。
代わりに Rational を使用すると、期待どおりの結果が得られます。
>> a = Rational(100)
>> b = Rational(51, 10)
>> c * b == a
=> true
もちろん、このトリックは有理数を扱っている場合にのみ適用されるため、凝ったもの (根や三角法など) は範囲外です。
これは正常な動作であり、まったく奇妙ではありません。
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