Project

General

Profile

Actions

Backport #7404

closed

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

Added by sho-h (Sho Hashimoto) over 11 years ago. Updated about 11 years ago.

Status:
Closed
[ruby-dev:46544]

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


Related issues 1 (0 open1 closed)

Related to Backport193 - Backport #7176: Rational can't be coerced into BigDecimal (TypeError)Closedusa (Usaku NAKAMURA)Actions

Updated by mame (Yusuke Endoh) over 11 years ago

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

Updated by mrkn (Kenta Murata) about 11 years ago

  • Status changed from Assigned to Closed
  • % Done changed from 0 to 100

This issue was solved with changeset r38801.
Sho, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


  • ext/bigdecimal/bigdecimal.c (BigDecimal_sub):
    need to specify precision for converting Rational and Float.
    [ruby-dev:46544] [Bug #7404]

  • ext/bigdecimal/bigdecimal.c (BigDecimal_mult): ditto.

  • ext/bigdecimal/bigdecimal.c (BigDecimal_divide): ditto.

  • ext/bigdecimal/bigdecimal.c (BigDecimal_DoDivmod): ditto.

  • ext/bigdecimal/bigdecimal.c (BigDecimal_divremain): ditto.

  • test/bigdecimal/test_bigdecimal.rb: add tests for the above fixes.

Actions #3

Updated by mrkn (Kenta Murata) about 11 years ago

  • Tracker changed from Bug to Backport
  • Project changed from Ruby master to Backport193
  • Status changed from Closed to Assigned
  • Assignee changed from mrkn (Kenta Murata) to usa (Usaku NAKAMURA)
  • Target version deleted (2.0.0)
Actions #4

Updated by usa (Usaku NAKAMURA) about 11 years ago

  • Status changed from Assigned to Closed

This issue was solved with changeset r38829.
Sho, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


merge revision(s) 38801,38809,38810: [Backport #7404]

* ext/bigdecimal/bigdecimal.c (BigDecimal_sub):
  need to specify precision for converting Rational and Float.
  [ruby-dev:46544] [Bug #7404]

* ext/bigdecimal/bigdecimal.c (BigDecimal_mult): ditto.

* ext/bigdecimal/bigdecimal.c (BigDecimal_divide): ditto.

* ext/bigdecimal/bigdecimal.c (BigDecimal_DoDivmod): ditto.

* ext/bigdecimal/bigdecimal.c (BigDecimal_divremain): ditto.

* test/bigdecimal/test_bigdecimal.rb: add tests for the above fixes.

* ext/bigdecimal/bigdecimal.c: use `RB_TYPE_P(x, t)` instead of
  `TYPE(x) == t`.

* ext/bigdecimal/bigdecimal.c (BigDecimal_to_s): use CRuby style.
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0