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
Updated by mame (Yusuke Endoh) almost 12 years ago
- Status changed from Open to Assigned
- Assignee set to mrkn (Kenta Murata)
- Target version set to 2.0.0
Updated by mrkn (Kenta Murata) almost 12 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.
Updated by mrkn (Kenta Murata) almost 12 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)
Updated by usa (Usaku NAKAMURA) almost 12 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.