Backport #7404
closedBigDecimal#add(Float) のみ BigDecimal を返し、他の四則演算では例外になる
Description
=begin
るりまの対応中に気付いたのですが、#7176 の対応により、BigDecimal#+ に Float を渡した場合、BigDecimal が返ってくるみたいなのですが、他の四則演算はそれ以前と同様に Float を返すようです。
例えば、BigDecimal#-、#sub を例にしますと、以下のように動作します。(#+ と #add だとすべて BigDecimal が返ります)
require "bigdecimal"
a = BigDecimal.new("1.1")
b = BigDecimal.new("2.2")
c = 3.3
p a - b # => #BigDecimal:f9232478,'-0.11E1',18(36)
p a - c # => -2.1999999999999997
p a.sub(b, 10) # => #BigDecimal:f923239c,'-0.11E1',18(36)
p a.sub(c, 0) # => -2.1999999999999997
p a.sub(c, 10) # => ArgumentError
BigDecimal#sub の実装である、BigDecimal_sub2 関数の以下の部分を通っていると思うのですが、c に Float が代入されるため、GetVpValue の時に例外になるのではないかと考えています。(第 2 引数に 0 を指定した場合は mx == 0 の方を通るため、結果が Float になるようです)
if (mx == 0) return BigDecimal_sub(self, b);
else {
size_t pl = VpSetPrecLimit(0);
VALUE c = BigDecimal_sub(self,b); /* ここでは Float オブジェクトが返っている */
VpSetPrecLimit(pl);
GUARD_OBJ(cv,GetVpValue(c,1)); /* ここで GetVpValueWithPrec の prec 引数に -1 が渡るため例外 */
VpLeftRound(cv,VpGetRoundMode(),mx);
return ToValue(cv);
}
BigDecimal#add と同じように、Rational と Float が渡された場合は、計算結果が BigDecimal になるようにするのがいいのではないかと思いました。
=end