From: Tadashi Saito Date: 2003-06-20T13:22:58+09:00 Subject: [ruby-dev:20392] [BigDecimal] proposal to change specification 斎藤と申します。 自分は勉強のために多倍長整数のライブラリを書いていまして、 関係するBigDecimalを知り、興味を持ちました。 BigDecimalは現状でもとても使えるライブラリだと思うのですが、 標準ライブラリとしてはまだまだ、既存クラスの仕様との すり合わせ・親和性などに改善の余地があるように思えます。 そこでBigDecimalについて、まずいくつか仕様変更の提案を させて下さい。 (タイミングが微妙ですみません…preview3リリースにあたっては 無視してくださって結構です) 今回提案するのは以下の4点です。 1.BigDecimal#** の追加 2.BigDecimal#infinite? の返り値の変更 3.BigDecimal#nonzero? の返り値の変更 4.BigDecimal#sign の削除 1. 現状では**が存在しないようですが、IntegerやFloatなど合わせ、 既存のBigDecimal#powerと同様のものとしてBigDecimal#**も 定義したらいかがでしょうか。 2. 現状のinfinite?は値が±∞/それ以外、でそれぞれtrue/falseを 返しているようですが、既存のFloat#infinite?に合わせ、値が -∞/+∞/その他、の場合に対応してそれぞれ、-1/1/nilを返した方が、 一貫していて分かりやすくなるのではないでしょうか。 3. nonzero?は、値がゼロの時にfalseを返していますが、 Numericでの定義通りnilを返した方がいいのではないでしょうか。 4. signは、7種類あるBigDeciamalインスタンスの属性   NaN、+0、-0、正、負、+∞、-∞ を判別するため、それぞれに対応した7つの定数のいづれかを返す メソッドです。しかし、 ・他の数値クラスにはsignメソッドがないので違和感がある ・既存のFloatでは、Float#nan?の真偽や0との比較、Float#infinite?の  正負で上記属性の判別をしている という点で、BigDecimal#signは無い方が自然ではないでしょうか。 BigDecimal#infinite?とBigDecimal#nonzero?の変更によって、 BigDecimal#signに代わってそちらでFloatと同様の判定ができるように なっています。 ところでsignを削除すると、BigDecimalでの+0/-0を直には判別できなく なってしまいます。しかしリファレンスマニュアルを見る限り、 Floatにおいても+0と-0を直接判別する方法がないようでしたので、 そちらに合わせました。 (やるとしたら、zero?がinfinity?と同様の値を返すように変更する くらいでしょうか) 今回の提案は以上です。採用していただければありがたいです。 しかし、実は提案したい点がまだまだまだまだたくさんあります。 これから何回かに分けて、少しずつメールを送っていこうと 思っていますので、よろしくお願いします。 以下、パッチをつけます。 Index: bigdecimal.c =================================================================== RCS file: /src/ruby/ext/bigdecimal/bigdecimal.c,v retrieving revision 1.6 diff -u -r1.6 bigdecimal.c --- bigdecimal.c 6 May 2003 13:18:26 -0000 1.6 +++ bigdecimal.c 20 Jun 2003 04:10:13 -0000 @@ -380,8 +380,9 @@ BigDecimal_IsInfinite(VALUE self) { Real *p = GetVpValue(self,1); - if(VpIsInf(p)) return Qtrue; - return Qfalse; + if(VpIsPosInf(p)) return INT2FIX(1); + if(VpIsNegInf(p)) return INT2FIX(-1); + return Qnil; } static VALUE @@ -547,7 +548,7 @@ BigDecimal_nonzero(VALUE self) { Real *a = GetVpValue(self,1); - return VpIsZero(a) ? Qfalse : self; + return VpIsZero(a) ? Qnil : self; } static VALUE @@ -1220,13 +1221,6 @@ } static VALUE -BigDecimal_sign(VALUE self) -{ /* sign */ - int s = GetVpValue(self,1)->sign; - return INT2FIX(s); -} - -static VALUE BigDecimal_sincos(VALUE self, VALUE nFig) { ENTER(5); @@ -1375,15 +1369,6 @@ rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW",INT2FIX(VP_EXCEPTION_OVERFLOW)); rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE",INT2FIX(VP_EXCEPTION_ZERODIVIDE)); - /* Constants for sign value */ - rb_define_const(rb_cBigDecimal, "SIGN_NaN",INT2FIX(VP_SIGN_NaN)); - rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_ZERO",INT2FIX(VP_SIGN_POSITIVE_ZERO)); - rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_ZERO",INT2FIX(VP_SIGN_NEGATIVE_ZERO)); - rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_FINITE",INT2FIX(VP_SIGN_POSITIVE_FINITE)); - rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_FINITE",INT2FIX(VP_SIGN_NEGATIVE_FINITE)); - rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_INFINITE",INT2FIX(VP_SIGN_POSITIVE_INFINITE)); - rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE",INT2FIX(VP_SIGN_NEGATIVE_INFINITE)); - /* instance methods */ rb_define_method(rb_cBigDecimal, "prec", BigDecimal_prec, 0); rb_define_method(rb_cBigDecimal, "assign", BigDecimal_assign2, 2); @@ -1415,6 +1400,7 @@ rb_define_method(rb_cBigDecimal, "floor", BigDecimal_floor, -1); rb_define_method(rb_cBigDecimal, "ceil", BigDecimal_ceil, -1); rb_define_method(rb_cBigDecimal, "power", BigDecimal_power, 1); + rb_define_method(rb_cBigDecimal, "**", BigDecimal_power, 1); rb_define_method(rb_cBigDecimal, "exp", BigDecimal_exp, 1); rb_define_method(rb_cBigDecimal, "sincos", BigDecimal_sincos, 1); rb_define_method(rb_cBigDecimal, "<=>", BigDecimal_comp, 1); @@ -1431,7 +1417,6 @@ rb_define_method(rb_cBigDecimal, "coerce", BigDecimal_coerce, 1); rb_define_method(rb_cBigDecimal, "inspect", BigDecimal_inspect, 0); rb_define_method(rb_cBigDecimal, "exponent", BigDecimal_exponent, 0); - rb_define_method(rb_cBigDecimal, "sign", BigDecimal_sign, 0); rb_define_method(rb_cBigDecimal, "nan?", BigDecimal_IsNaN, 0); rb_define_method(rb_cBigDecimal, "infinite?", BigDecimal_IsInfinite, 0); rb_define_method(rb_cBigDecimal, "finite?", BigDecimal_IsFinite, 0); --- 斎藤ただし