[ruby-trunk - Bug #7404][Open] BigDecimal#add(Float) のみ BigDecimal を返し、他の四則演算では例外になる

Issue #7404 has been reported by sho-h (Sho H.).


Bug #7404: BigDecimal#add(Float) のみ BigDecimal を返し、他の四則演算では例外になる

Author: sho-h (Sho H.)
Status: Open
Priority: Normal
Assignee:
Category:
Target version:
ruby -v: ruby 2.0.0dev (2012-11-19 trunk 37734) [x86_64-linux]

=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

Issue #7404 has been updated by mame (Yusuke E.).

Status changed from Open to Assigned
Assignee set to mrkn (Kenta M.)
Target version set to 2.0.0


Bug #7404: BigDecimal#add(Float) のみ BigDecimal を返し、他の四則演算では例外になる

Author: sho-h (Sho H.)
Status: Assigned
Priority: Normal
Assignee: mrkn (Kenta M.)
Category:
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-11-19 trunk 37734) [x86_64-linux]

=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