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

Posted by sho-h (Sho Hashimoto) (Guest)
on 2012-11-19 16:12
(Received via mailing list)
Issue #7404 has been reported by sho-h (Sho Hashimoto).

----------------------------------------
Bug #7404: BigDecimal#add(Float) のみ BigDecimal を返し、他の四則演算では例外になる
https://bugs.ruby-lang.org/issues/7404

Author: sho-h (Sho Hashimoto)
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
Posted by mame (Yusuke Endoh) (Guest)
on 2012-11-24 10:19
(Received via mailing list)
Issue #7404 has been updated by mame (Yusuke Endoh).

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


----------------------------------------
Bug #7404: BigDecimal#add(Float) のみ BigDecimal を返し、他の四則演算では例外になる
https://bugs.ruby-lang.org/issues/7404#change-33806

Author: sho-h (Sho Hashimoto)
Status: Assigned
Priority: Normal
Assignee: mrkn (Kenta Murata)
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
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.