斎藤と申します。

自分は勉強のために多倍長整数のライブラリを書いていまして、
関係する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);

---
斎藤ただし