Project

General

Profile

Actions

Bug #2662

closed

BigDecimal#ceil, etc. should not return Integer

Added by mame (Yusuke Endoh) over 12 years ago. Updated about 11 years ago.

Status:
Rejected
Priority:
Normal
Target version:
ruby -v:
ruby 1.9.2dev (2010-01-27 trunk 26434) [i686-linux]
Backport:
[ruby-dev:40168]

Description

=begin
まつもとさん
遠藤です。

r20584 と r20616 で BigDecimal#ceil 、truncate 、floor 、round 、div の
戻り値を Integer にする変更がありますが、これだと巨大な BigDecimal を
扱えなく、または扱いが面倒になります。

巨大な BigDecimal は ceil が取れない

$ ./ruby -rbigdecimal -e 'p BigDecimal("1E100000").ceil'
(巨大な Bignum を確保しようとして固まる...)

Infinity が混ざるときは自分で対処する必要がある

$ ./ruby -rbigdecimal -e 'p BigDecimal("Infinity").ceil'
-e:1:in ceil': Computation results to 'Infinity' (FloatDomainError) from -e:1:in '

Float#ceil などが Integer を返すのに合わせるためだと思いますが、この変更
では BigDecimal のありがたみ自体が減ってしまう気がします。
どうしてもということでなければ、revert を提案します。

diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index c6ffe98..1f51f61 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -1108,7 +1108,7 @@ BigDecimal_div2(int argc, VALUE *argv, VALUE self)
Real *div=NULL;
Real *mod;
if(BigDecimal_DoDivmod(self,b,&div,&mod)) {

  • return BigDecimal_to_i(ToValue(div));
  • return ToValue(div);
    }
    return DoSomeOne(self,b,rb_intern("div"));
    } else { /* div in BigDecimal sense */
    @@ -1308,9 +1308,6 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
    GUARD_OBJ(c,VpCreateRbObject(mx, "0"));
    VpSetPrecLimit(pl);
    VpActiveRound(c,a,sw,iLoc);
  • if (argc == 0) {
  • return BigDecimal_to_i(ToValue(c));
  • }
    return ToValue(c);
    }

@@ -1355,9 +1352,6 @@ BigDecimal_truncate(int argc, VALUE argv, VALUE self)
GUARD_OBJ(c,VpCreateRbObject(mx, "0"));
VpSetPrecLimit(pl);
VpActiveRound(c,a,VP_ROUND_DOWN,iLoc); /
0: truncate */

  • if (argc == 0) {
  • return BigDecimal_to_i(ToValue(c));
  • }
    return ToValue(c);
    }

@@ -1418,9 +1412,6 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
GUARD_OBJ(c,VpCreateRbObject(mx, "0"));
VpSetPrecLimit(pl);
VpActiveRound(c,a,VP_ROUND_FLOOR,iLoc);

  • if (argc == 0) {
  • return BigDecimal_to_i(ToValue(c));
  • }
    return ToValue(c);
    }

@@ -1465,9 +1456,6 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
GUARD_OBJ(c,VpCreateRbObject(mx, "0"));
VpSetPrecLimit(pl);
VpActiveRound(c,a,VP_ROUND_CEIL,iLoc);

  • if (argc == 0) {
  • return BigDecimal_to_i(ToValue(c));
  • }
    return ToValue(c);
    }

ついでに、この変更で rubyspec がやっぱりいっぱい失敗しています。

BigDecimal#ceil returns the smallest integer greater or equal to self, if n is unspecified ERROR
FloatDomainError: Computation results to 'Infinity'
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/ceil_spec.rb:34:in ceil' /home/mame/work/ruby/spec/rubyspec/library/bigdecimal/ceil_spec.rb:34:in block (2 levels) in <top (required)>'
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/ceil_spec.rb:4:in `<top (required)>'

BigDecimal#div with precision set to 0 returns NaN if NaN is involved ERROR
FloatDomainError: Computation results to 'NaN'(Not a Number)
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/shared/quo.rb:34:in div' /home/mame/work/ruby/spec/rubyspec/library/bigdecimal/shared/quo.rb:34:in block (2 levels) in <top (required)>'
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/div_spec.rb:5:in `<top (required)>'

BigDecimal#div returns NaN if NaN is involved ERROR
FloatDomainError: Computation results to 'NaN'(Not a Number)
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/div_spec.rb:46:in div' /home/mame/work/ruby/spec/rubyspec/library/bigdecimal/div_spec.rb:46:in block (2 levels) in <top (required)>'
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/div_spec.rb:12:in `<top (required)>'

BigDecimal#div returns NaN if divided by Infinity and no precision given ERROR
FloatDomainError: Computation results to 'NaN'(Not a Number)
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/div_spec.rb:51:in div' /home/mame/work/ruby/spec/rubyspec/library/bigdecimal/div_spec.rb:51:in block (2 levels) in <top (required)>'
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/div_spec.rb:12:in `<top (required)>'

BigDecimal#div returns NaN if (+|-) Infinity divided by 1 and no precision given ERROR
FloatDomainError: Computation results to 'NaN'(Not a Number)
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/div_spec.rb:109:in div' /home/mame/work/ruby/spec/rubyspec/library/bigdecimal/div_spec.rb:109:in block (2 levels) in <top (required)>'
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/div_spec.rb:12:in `<top (required)>'

BigDecimal#floor returns the greatest integer smaller or equal to self ERROR
FloatDomainError: Computation results to 'Infinity'
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/floor_spec.rb:29:in floor' /home/mame/work/ruby/spec/rubyspec/library/bigdecimal/floor_spec.rb:29:in block (2 levels) in <top (required)>'
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/floor_spec.rb:4:in `<top (required)>'

BigDecimal#truncate returns value of type Bigdecimal. FAILED
Expected false
to equal true

/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/truncate_spec.rb:16:in block (3 levels) in <top (required)>' /home/mame/work/ruby/spec/rubyspec/library/bigdecimal/truncate_spec.rb:15:in each'
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/truncate_spec.rb:15:in block (2 levels) in <top (required)>' /home/mame/work/ruby/spec/rubyspec/library/bigdecimal/truncate_spec.rb:4:in <top (required)>'

BigDecimal#truncate returns NaN if self is NaN ERROR
FloatDomainError: Computation results to 'NaN'(Not a Number)
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/truncate_spec.rb:64:in truncate' /home/mame/work/ruby/spec/rubyspec/library/bigdecimal/truncate_spec.rb:64:in block (2 levels) in <top (required)>'
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/truncate_spec.rb:4:in `<top (required)>'

BigDecimal#truncate returns Infinity if self is infinite ERROR
FloatDomainError: Computation results to 'Infinity'
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/truncate_spec.rb:71:in truncate' /home/mame/work/ruby/spec/rubyspec/library/bigdecimal/truncate_spec.rb:71:in block (2 levels) in <top (required)>'
/home/mame/work/ruby/spec/rubyspec/library/bigdecimal/truncate_spec.rb:4:in `<top (required)>'

--
Yusuke Endoh
=end

Actions

Also available in: Atom PDF