Ruby の型 (精度やスケールの長さが異なっていても) を正確に計算する必要があるという私の理解は正しいBigDecimal
ですか?
Rails アプリケーション内のすべての値はBigDecimal
型であり、いくつかのエラーが表示されます (10 進数の長さが異なります)。これがオブジェクト型ではなくメソッドであることを願っています。
Ruby の型 (精度やスケールの長さが異なっていても) を正確に計算する必要があるという私の理解は正しいBigDecimal
ですか?
Rails アプリケーション内のすべての値はBigDecimal
型であり、いくつかのエラーが表示されます (10 進数の長さが異なります)。これがオブジェクト型ではなくメソッドであることを願っています。
浮動小数点演算を扱う場合、よくある落とし穴が 2 つあります。
最初の問題は、Ruby の浮動小数点の精度が固定されていることです。実際には、これは 1) 問題がないか、2) 破滅的か、3) その中間かのいずれかになります。次の点を考慮してください。
# float
1.0e+25 - 9999999999999999900000000.0
#=> 0.0
# bigdecimal
BigDecimal("1.0e+25") - BigDecimal("9999999999999999900000000.0")
#=> 100000000
1億の精度差!かなり深刻ですよね?
ただし、精度誤差は元の数値の約 0.000000000000001% にすぎません。これが問題であるかどうかを判断するのは、実際にはあなた次第です。BigDecimal
しかし、任意の精度を持つため、使用することで問題は解消されます。唯一の制限は、Ruby で使用できるメモリです。
2 つ目の問題は、浮動小数点がすべての分数を正確に表現できないことです。特に、Ruby (および他のほとんどの言語) の浮動小数点数は2 進浮動小数点であるため、小数に関して問題があります。たとえば、小数は永遠に繰り返される 2 進数の分数です ( )。これは、精度に関係なく、2 進浮動小数点に正確に格納することはできません。0.2
0.001100110011...
これは、数値を丸めるときに大きな違いを生む可能性があります。検討:
# float
(0.29 * 50).round
#=> 14 # not correct
# bigdecimal
(BigDecimal("0.29") * 50).round
#=> 15 # correct
ABigDecimal
は小数を正確に表すことができます。ただし、小数でも正確に記述できない分数があります。たとえば1/9
、永遠に繰り返される小数 ( 0.1111111111111...
) です。
繰り返しますが、これは数値を四捨五入するときに噛みつきます。検討:
# bigdecimal
(BigDecimal("1") / 9 * 9 / 2).round
#=> 0 # not correct
この場合、10 進浮動小数点を使用すると、丸め誤差が発生します。
いくつかの結論:
BigDecimal
もうまく機能し、それらが 10 進浮動小数点か 2 進浮動小数点かはあまり気にしません。