From: Tadashi Saito Date: 2003-07-13T03:15:01+09:00 Subject: [ruby-dev:20644] [BigDecimal] dup and to_f 斎藤です。 BigDecimalにはBigDecimal#dupが存在しますが、1.8の方針から見ると 望ましくないと思います。 また、BigDecimal#to_fはdupのaliasとして、つまりself(と同じ値)を そのまま返すよう定義されていますが、やはりFloatを返すべきでしょう。 以上2点を修正してみました。パッチではとりあえず、dupを USE_MUTABLE_METHODの中に入れる形にして、ドキュメントからは 削除しました。 以下、ドキュメントの修正とまとめてパッチです。小林さん、 取り込んでいただけますでしょうか。 # 値がFloatに収まらないときは、RangeErrorより警告のみの方が # 良かったりするのでしょうか…エラーにしている箇所が多そう # だったので、とりあえずそうしてみました。 Index: bigdecimal.c =================================================================== RCS file: /src/ruby/ext/bigdecimal/bigdecimal.c,v retrieving revision 1.9 diff -u -r1.9 bigdecimal.c --- bigdecimal.c 1 Jul 2003 14:14:18 -0000 1.9 +++ bigdecimal.c 12 Jul 2003 17:58:50 -0000 @@ -31,11 +31,13 @@ */ #include +#include +#include +#include #include #include #include #include "ruby.h" -#include "math.h" #include "version.h" /* #define USE_MUTABLE_METHOD */ @@ -442,6 +444,30 @@ } static VALUE +BigDecimal_to_f(VALUE self) +{ + ENTER(1); + Real *p; + double d, d2; + S_LONG e; + + GUARD_OBJ(p,GetVpValue(self,1)); + VpVtoD(&d, &e, p); + if(d == 0.0 || isinf(d) || isnan(d)) + return rb_float_new(d); + errno = 0; + d2 = pow(10.0, e); + if(errno == ERANGE || (d2 == 0.0 && d != 0.0) + || d > DBL_MAX / d2 || d < DBL_MIN / d2) { + U_LONG nc = VpNumOfChars(p)+1; + char *psz = ALLOCA_N(char, nc); + VpToString(p, psz, 0); + rb_raise(rb_eRangeError, "BigDecimal %s out of Float range", psz); + } + return rb_float_new(d*d2); +} + +static VALUE BigDecimal_induced_from(VALUE self, VALUE x) { Real *p = GetVpValue(x,1); @@ -867,19 +893,6 @@ } static VALUE -BigDecimal_dup(VALUE self) -{ - ENTER(5); - Real *c, *a; - U_LONG mx; - GUARD_OBJ(a,GetVpValue(self,1)); - mx = a->Prec *(VpBaseFig() + 1); - GUARD_OBJ(c,VpCreateRbObject(mx, "0")); - VpAsgn(c, a, 1); - return ToValue(c); -} - -static VALUE BigDecimal_abs(VALUE self) { ENTER(5); @@ -1348,6 +1361,19 @@ f = VpMult(cv,av,bv); return INT2NUM(f); } + +static VALUE +BigDecimal_dup(VALUE self) +{ + ENTER(5); + Real *c, *a; + U_LONG mx; + GUARD_OBJ(a,GetVpValue(self,1)); + mx = a->Prec *(VpBaseFig() + 1); + GUARD_OBJ(c,VpCreateRbObject(mx, "0")); + VpAsgn(c, a, 1); + return ToValue(c); +} #endif /* USE_MUTABLE_METHOD */ void @@ -1417,8 +1443,7 @@ rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1); rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1); rb_define_method(rb_cBigDecimal, "divmod", BigDecimal_divmod, 1); - rb_define_method(rb_cBigDecimal, "dup", BigDecimal_dup, 0); - rb_define_method(rb_cBigDecimal, "to_f", BigDecimal_dup, 0); /* to_f === dup */ + rb_define_method(rb_cBigDecimal, "to_f", BigDecimal_to_f, 0); rb_define_method(rb_cBigDecimal, "abs", BigDecimal_abs, 0); rb_define_method(rb_cBigDecimal, "sqrt", BigDecimal_sqrt, 1); rb_define_method(rb_cBigDecimal, "fix", BigDecimal_fix, 0); @@ -1457,6 +1482,7 @@ rb_define_singleton_method(rb_cBigDecimal, "sub!", BigDecimal_sub3, 3); rb_define_singleton_method(rb_cBigDecimal, "mult!", BigDecimal_mult3, 3); rb_define_singleton_method(rb_cBigDecimal, "div!",BigDecimal_divmod4, 4); + rb_define_method(rb_cBigDecimal, "dup", BigDecimal_dup, 0); #endif /* USE_MUTABLE_METHOD */ } @@ -3415,6 +3441,21 @@ *d = VpGetDoubleNegZero(); *e = 0; goto Exit; + } else + if(VpIsPosInf(m)) { + *d = VpGetDoublePosInf(); + *e = 0; + goto Exit; + } else + if(VpIsNegInf(m)) { + *d = VpGetDoubleNegInf(); + *e = 0; + goto Exit; + } else + if(VpIsNaN(m)) { + *d = VpGetDoubleNaN(); + *e = 0; + goto Exit; } ind_m = 0; mm = Min(fig,(m->Prec)); Index: bigdecimal_en.html =================================================================== RCS file: /src/ruby/ext/bigdecimal/bigdecimal_en.html,v retrieving revision 1.4 diff -u -r1.4 bigdecimal_en.html --- bigdecimal_en.html 27 Jun 2003 04:38:57 -0000 1.4 +++ bigdecimal_en.html 12 Jul 2003 17:58:50 -0000 @@ -394,8 +394,7 @@
  • to_f
  • -same as dup method. -creates a new BigDecimal object having same value. +creates a new Float object having same value.
    @@ -455,10 +454,6 @@ '0.314E1' is the value,4 is the number of the significant digits, and 12 is the maximum number of the significant digits the object can hold. - - -
  • dup
  • -creates a new BigDecimal object having same value.
  • sqrt
  • Index: bigdecimal_ja.html =================================================================== RCS file: /src/ruby/ext/bigdecimal/bigdecimal_ja.html,v retrieving revision 1.4 diff -u -r1.4 bigdecimal_ja.html --- bigdecimal_ja.html 27 Jun 2003 04:38:57 -0000 1.4 +++ bigdecimal_ja.html 12 Jul 2003 17:58:51 -0000 @@ -374,8 +374,7 @@ a が Infinity や NaN のとき、i は nil になります。
  • to_f
  • -dup と全く同じです。 -同じ値の BigDecimal オブジェクトを生成します。 +同じ値の Float オブジェクトを生成します。
  • to_s[(n)]
  • 文字列に変換します("0.xxxxxEn"の形になります)。
    @@ -444,9 +443,6 @@ 次の4は現在の有効桁数(表示より若干大きいことがあります)、 最後はオブジェクトが取り得る最大桁数になります。 -
    -
  • dup
  • -同じ値の BigDecimal オブジェクトを生成します。
  • sqrt
  • aの有効桁 n 桁の平方根(n の平方根ではありません)。 --- 斎藤ただし