diff options
author | shigek <shigek@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-06-27 04:38:57 +0000 |
---|---|---|
committer | shigek <shigek@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-06-27 04:38:57 +0000 |
commit | d3ce235babf3a5fa9a7904c45ec193e8962fe845 (patch) | |
tree | 6d2a550cb79cddaee7a52a6aae149d1b3f0d3c16 /ext | |
parent | 7e91b4b546634afa0203f7bd6d0e5092f8f7ee61 (diff) | |
download | ruby-d3ce235babf3a5fa9a7904c45ec193e8962fe845.tar.gz |
1.From Tadashi Saito's advice
to_parts changed to split,assign removed, ** added,bugs in infinite? & nozero? fixed.
2.Rounding functionalities added
mode now accepts rounding mode.
round accepts second argument for Bankers' rounding.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4008 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r-- | ext/bigdecimal/bigdecimal.c | 321 | ||||
-rw-r--r-- | ext/bigdecimal/bigdecimal.h | 19 | ||||
-rw-r--r-- | ext/bigdecimal/bigdecimal_en.html | 507 | ||||
-rw-r--r-- | ext/bigdecimal/bigdecimal_ja.html | 507 |
4 files changed, 740 insertions, 614 deletions
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c index 62343830ac..f1bd1e2320 100644 --- a/ext/bigdecimal/bigdecimal.c +++ b/ext/bigdecimal/bigdecimal.c @@ -34,14 +34,6 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#ifdef NT -#include <malloc.h> -#ifdef _MSC_VER -#include <float.h> -#define isnan(x) _isnan(x) -#define isinf(x) (!(_finite(x))) -#endif /* _MSC_VER */ -#endif /* defined NT */ #include "ruby.h" #include "math.h" #include "version.h" @@ -52,7 +44,7 @@ VALUE rb_cBigDecimal; #include "bigdecimal.h" -/* MACRO's to guard objects from GC by keeping it in stack */ +/* MACRO's to guard objects from GC by keeping them in stack */ #define ENTER(n) volatile VALUE vStack[n];int iStack=0 #define PUSH(x) vStack[iStack++] = (unsigned long)(x); #define SAVE(p) PUSH(p->obj); @@ -71,7 +63,9 @@ static int VpSubAbs(Real *a,Real *b,Real *c); static U_LONG VpSetPTR(Real *a,Real *b,Real *c,U_LONG *a_pos,U_LONG *b_pos,U_LONG *c_pos,U_LONG *av,U_LONG *bv); static int VpNmlz(Real *a); static void VpFormatSt(char *psz,S_INT fFmt); -static int VpRdup(Real *m); +static int VpRdup(Real *m,U_LONG ind_m); +static int VpInternalRound(Real *c,int ixDigit,U_LONG vPrev,U_LONG v); + static U_LONG SkipWhiteChar(char *szVal); /* @@ -297,25 +291,32 @@ BigDecimal_load(VALUE self, VALUE str) static VALUE BigDecimal_mode(VALUE self, VALUE which, VALUE val) { - unsigned short fo = VpGetException(); - unsigned short f; - - if(TYPE(which)!=T_FIXNUM) return INT2FIX(fo); - if(val!=Qfalse && val!=Qtrue) return INT2FIX(fo); + unsigned long f,fo; + + if(TYPE(which)!=T_FIXNUM) return Qnil; + f = (unsigned long)FIX2INT(which); - f = (unsigned short)FIX2INT(which); - if(f&VP_EXCEPTION_INFINITY) { + if(f&VP_EXCEPTION_ALL) { + /* Exception mode setting */ fo = VpGetException(); - VpSetException((unsigned short)((val==Qtrue)?(fo|VP_EXCEPTION_INFINITY): - (fo&(~VP_EXCEPTION_INFINITY)))); + if(val!=Qfalse && val!=Qtrue) return Qnil; + if(f&VP_EXCEPTION_INFINITY) { + VpSetException((unsigned short)((val==Qtrue)?(fo|VP_EXCEPTION_INFINITY): + (fo&(~VP_EXCEPTION_INFINITY)))); + } + if(f&VP_EXCEPTION_NaN) { + VpSetException((unsigned short)((val==Qtrue)?(fo|VP_EXCEPTION_NaN): + (fo&(~VP_EXCEPTION_NaN)))); + } + return INT2FIX(fo); } - if(f&VP_EXCEPTION_NaN) { - fo = VpGetException(); - VpSetException((unsigned short)((val==Qtrue)?(fo|VP_EXCEPTION_NaN): - (fo&(~VP_EXCEPTION_NaN)))); + if(VP_COMP_MODE==f) { + /* Computaion mode setting */ + if(TYPE(val)!=T_FIXNUM) return Qnil; + fo = VpSetCompMode((unsigned long)FIX2INT(val)); + return INT2FIX(fo); } - fo = VpGetException(); - return INT2FIX(fo); + return Qnil; } static U_LONG @@ -380,8 +381,9 @@ static VALUE 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 +549,7 @@ static VALUE BigDecimal_nonzero(VALUE self) { Real *a = GetVpValue(self,1); - return VpIsZero(a) ? Qfalse : self; + return VpIsZero(a) ? Qnil : self; } static VALUE @@ -650,6 +652,7 @@ BigDecimal_mult(VALUE self, VALUE r) static VALUE BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r) +/* For c,res = self.div(r): no round operation */ { ENTER(5); Real *a, *b; @@ -669,16 +672,19 @@ BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r) static VALUE BigDecimal_div(VALUE self, VALUE r) +/* For c = self/r: with round operation */ { ENTER(5); Real *c=NULL, *res=NULL, *div = NULL; r = BigDecimal_divide(&c, &res, &div, self, r); SAVE(c);SAVE(res);SAVE(div); if(r!=(VALUE)0) return r; /* coerced by other */ - if(res->frac[0]*2>=div->frac[0]) { - /* Round up */ - VpRdup(c); - } + /* a/b = c + r/b */ + /* c xxxxx + r 00000yyyyy ==> (y/b)*BASE >= HALF_BASE + */ + /* Round up ? */ + VpInternalRound(c,0,c->frac[c->Prec-1],(VpBaseVal()*res->frac[0])/div->frac[0]); return ToValue(c); } @@ -707,7 +713,7 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod) VpDivd(c, res, a, b); mx = c->Prec *(VpBaseFig() + 1); GUARD_OBJ(d,VpCreateRbObject(mx, "0")); - VpRound(d,c,1,3,0); + VpActiveRound(d,c,VP_COMP_MODE_FLOOR,0); VpMult(res,d,b); VpAddSub(c,a,res,-1); *div = d; @@ -754,7 +760,7 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv) GUARD_OBJ(d,VpCreateRbObject(mx, "0")); GUARD_OBJ(f,VpCreateRbObject(mx, "0")); - VpRound(d,c,1,1,0); /* 1: round off */ + VpActiveRound(d,c,VP_COMP_MODE_TRUNCATE,0); /* 0: round off */ VpFrac(f, c); VpMult(rr,f,b); @@ -814,20 +820,6 @@ BigDecimal_divmod2(VALUE self, VALUE b, VALUE n) } static VALUE -BigDecimal_assign2(VALUE self, VALUE n, VALUE f) -{ - ENTER(5); - Real *cv; - Real *av; - U_LONG mx = (U_LONG)GetPositiveInt(n); - Check_Type(f, T_FIXNUM); - GUARD_OBJ(cv,VpCreateRbObject(mx,"0")); - GUARD_OBJ(av,GetVpValue(self,1)); - VpAsgn(cv,av,FIX2INT(f)); - return ToValue(cv); -} - -static VALUE BigDecimal_add2(VALUE self, VALUE b, VALUE n) { ENTER(5); @@ -928,7 +920,7 @@ BigDecimal_fix(VALUE self) GUARD_OBJ(a,GetVpValue(self,1)); mx = a->Prec *(VpBaseFig() + 1); GUARD_OBJ(c,VpCreateRbObject(mx, "0")); - VpRound(c,a,1,1,0); /* 1: round off */ + VpActiveRound(c,a,VP_COMP_MODE_TRUNCATE,0); /* 0: round off */ return ToValue(c); } @@ -941,19 +933,29 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self) int sw; U_LONG mx; VALUE vLoc; - - if(rb_scan_args(argc,argv,"01",&vLoc)==0) { + VALUE vBanker; + int na = rb_scan_args(argc,argv,"02",&vLoc,&vBanker); + sw = VP_COMP_MODE_ROUNDUP; /* round up */ + switch(na) { + case 0: iLoc = 0; - } else { + break; + case 1: + Check_Type(vLoc, T_FIXNUM); + iLoc = FIX2INT(vLoc); + break; + case 2: Check_Type(vLoc, T_FIXNUM); iLoc = FIX2INT(vLoc); + Check_Type(vBanker, T_FIXNUM); + if(FIX2INT(vBanker)) sw = VP_COMP_MODE_EVEN; /* Banker's rounding */ + break; } - sw = 2; GUARD_OBJ(a,GetVpValue(self,1)); mx = a->Prec *(VpBaseFig() + 1); GUARD_OBJ(c,VpCreateRbObject(mx, "0")); - VpRound(c,a,sw,1,iLoc); + VpActiveRound(c,a,sw,iLoc); return ToValue(c); } @@ -973,12 +975,11 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self) Check_Type(vLoc, T_FIXNUM); iLoc = FIX2INT(vLoc); } - sw = 1; /* truncate */ GUARD_OBJ(a,GetVpValue(self,1)); mx = a->Prec *(VpBaseFig() + 1); GUARD_OBJ(c,VpCreateRbObject(mx, "0")); - VpRound(c,a,sw,1,iLoc); + VpActiveRound(c,a,VP_COMP_MODE_TRUNCATE,iLoc); /* 0: truncate */ return ToValue(c); } @@ -1015,7 +1016,7 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self) GUARD_OBJ(a,GetVpValue(self,1)); mx = a->Prec *(VpBaseFig() + 1); GUARD_OBJ(c,VpCreateRbObject(mx, "0")); - VpRound(c,a,1,3,iLoc); + VpActiveRound(c,a,VP_COMP_MODE_FLOOR,iLoc); return ToValue(c); } @@ -1038,7 +1039,7 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self) GUARD_OBJ(a,GetVpValue(self,1)); mx = a->Prec *(VpBaseFig() + 1); GUARD_OBJ(c,VpCreateRbObject(mx, "0")); - VpRound(c,a,1,2,iLoc); + VpActiveRound(c,a,VP_COMP_MODE_CEIL,iLoc); return ToValue(c); } @@ -1064,7 +1065,7 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self) } static VALUE -BigDecimal_to_parts(VALUE self) +BigDecimal_split(VALUE self) { ENTER(5); Real *vp; @@ -1366,8 +1367,10 @@ Init_bigdecimal(void) rb_define_singleton_method(rb_cBigDecimal, "induced_from",BigDecimal_induced_from, 1); rb_define_singleton_method(rb_cBigDecimal, "_load", BigDecimal_load, 1); - /* Constants */ + /* Constants definition */ rb_define_const(rb_cBigDecimal, "BASE", INT2FIX((S_INT)VpBaseVal())); + + /* Exceptions */ rb_define_const(rb_cBigDecimal, "EXCEPTION_ALL",INT2FIX(VP_EXCEPTION_ALL)); rb_define_const(rb_cBigDecimal, "EXCEPTION_NaN",INT2FIX(VP_EXCEPTION_NaN)); rb_define_const(rb_cBigDecimal, "EXCEPTION_INFINITY",INT2FIX(VP_EXCEPTION_INFINITY)); @@ -1375,6 +1378,14 @@ Init_bigdecimal(void) rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW",INT2FIX(VP_EXCEPTION_OVERFLOW)); rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE",INT2FIX(VP_EXCEPTION_ZERODIVIDE)); + /* Computation mode */ + rb_define_const(rb_cBigDecimal, "COMP_MODE",INT2FIX(VP_COMP_MODE)); + rb_define_const(rb_cBigDecimal, "COMP_MODE_TRUNCATE",INT2FIX(VP_COMP_MODE_TRUNCATE)); + rb_define_const(rb_cBigDecimal, "COMP_MODE_ROUNDUP",INT2FIX(VP_COMP_MODE_ROUNDUP)); + rb_define_const(rb_cBigDecimal, "COMP_MODE_CEIL",INT2FIX(VP_COMP_MODE_CEIL)); + rb_define_const(rb_cBigDecimal, "COMP_MODE_FLOOR",INT2FIX(VP_COMP_MODE_FLOOR)); + rb_define_const(rb_cBigDecimal, "COMP_MODE_EVEN",INT2FIX(VP_COMP_MODE_EVEN)); + /* 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)); @@ -1386,7 +1397,6 @@ Init_bigdecimal(void) /* instance methods */ rb_define_method(rb_cBigDecimal, "prec", BigDecimal_prec, 0); - rb_define_method(rb_cBigDecimal, "assign", BigDecimal_assign2, 2); rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2); rb_define_method(rb_cBigDecimal, "sub", BigDecimal_sub2, 2); rb_define_method(rb_cBigDecimal, "mult", BigDecimal_mult2, 2); @@ -1394,7 +1404,7 @@ Init_bigdecimal(void) rb_define_method(rb_cBigDecimal, "hash", BigDecimal_hash, 0); rb_define_method(rb_cBigDecimal, "to_s", BigDecimal_to_s, -1); rb_define_method(rb_cBigDecimal, "to_i", BigDecimal_to_i, 0); - rb_define_method(rb_cBigDecimal, "to_parts", BigDecimal_to_parts, 0); + rb_define_method(rb_cBigDecimal, "split", BigDecimal_split, 0); rb_define_method(rb_cBigDecimal, "+", BigDecimal_add, 1); rb_define_method(rb_cBigDecimal, "-", BigDecimal_sub, 1); rb_define_method(rb_cBigDecimal, "+@", BigDecimal_uplus, 0); @@ -1415,6 +1425,7 @@ Init_bigdecimal(void) 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); @@ -1462,6 +1473,8 @@ static int gfCheckVal = 1; /* Value checking flag in VpNmlz() */ #endif /* _DEBUG */ static U_LONG gnPrecLimit = 0; /* Global upper limit of the precision newly allocated */ +static short gfCompMode = VP_COMP_MODE_ROUNDUP; /* Mode for general computation */ + static U_LONG BASE_FIG = 4; /* =log10(BASE) */ static U_LONG BASE = 10000L; /* Base value(value must be 10**BASE_FIG) */ /* The value of BASE**2 + BASE must be represented */ @@ -1544,6 +1557,22 @@ VpSetPrecLimit(U_LONG n) return s; } +VP_EXPORT unsigned long +VpGetCompMode(void) +{ + return gfCompMode; +} + +VP_EXPORT unsigned long +VpSetCompMode(unsigned long n) +{ + unsigned long s = gfCompMode; + if(n!=VP_COMP_MODE_TRUNCATE && n!= VP_COMP_MODE_ROUNDUP && n!=VP_COMP_MODE_CEIL && + n!=VP_COMP_MODE_FLOOR && n!= VP_COMP_MODE_EVEN) return s; + gfCompMode = n; + return s; +} + /* * 0.0 & 1.0 generator * These gZero_..... and gOne_..... can be any name @@ -1552,8 +1581,8 @@ VpSetPrecLimit(U_LONG n) * (to let the compiler know they may be changed in outside * (... but not actually..)). */ -double gZero_ABCED9B1_CE73__00400511F31D = 0.0; -double gOne_ABCED9B4_CE73__00400511F31D = 1.0; +volatile double gZero_ABCED9B1_CE73__00400511F31D = 0.0; +volatile double gOne_ABCED9B4_CE73__00400511F31D = 1.0; static double Zero(void) { @@ -1969,10 +1998,10 @@ VpAlloc(U_LONG mx, char *szVal) ++i; ++ni; } - nf = 0; + nf = 0; ipf = 0; ipe = 0; - ne = 0; + ne = 0; if(v) { /* other than digit nor \0 */ if(szVal[i] == '.') { /* xxx. */ @@ -2023,11 +2052,10 @@ VpAlloc(U_LONG mx, char *szVal) * [Input] * a ... RHSV * isw ... switch for assignment. - * c = a when isw = 1 or 2 - * c = -a when isw = -1 or -1 - * when |isw|==1 - * if c->MaxPrec < a->Prec,then round up - * will not be performed. + * c = a when isw > 0 + * c = -a when isw < 0 + * if c->MaxPrec < a->Prec,then round operation + * will be performed. * [Output] * c ... LHSV */ @@ -2051,22 +2079,19 @@ VpAsgn(Real *c, Real *a, int isw) n =(a->Prec < c->MaxPrec) ?(a->Prec) :(c->MaxPrec); c->Prec = n; for(j=0;j < n; ++j) c->frac[j] = a->frac[j]; - if(isw < 0) isw = -isw; - if(isw == 2) { - if(a->MaxPrec>n) { - if((c->Prec < a->Prec) && - (a->frac[n] >= HALF_BASE)) VpRdup(c); /* round up/off */ - } + /* Needs round ? */ + if(c->Prec < a->Prec) { + VpInternalRound(c,n,(n>0)?a->frac[n-1]:0,a->frac[n]); } } else { /* The value of 'a' is zero. */ VpSetZero(c,isw*VpGetSign(a)); return 1; } - VpNmlz(c); return c->Prec*BASE_FIG; } + /* * c = a + b when operation = 1 or 2 * = a - b when operation = -1 or -2. @@ -2113,7 +2138,7 @@ VpAddSub(Real *c, Real *a, Real *b, int operation) } if(operation < 0) sw = -1; - else sw = 1; + else sw = 1; /* compare absolute value. As a result,|a_ptr|>=|b_ptr| */ if(a->exponent > b->exponent) { @@ -2202,7 +2227,6 @@ static int VpAddAbs(Real *a, Real *b, Real *c) { U_LONG word_shift; - U_LONG round; U_LONG carry; U_LONG ap; U_LONG bp; @@ -2210,7 +2234,7 @@ VpAddAbs(Real *a, Real *b, Real *c) U_LONG a_pos; U_LONG b_pos; U_LONG c_pos; - U_LONG av, bv; + U_LONG av, bv, mrv; #ifdef _DEBUG if(gfDebug) { @@ -2226,7 +2250,7 @@ VpAddAbs(Real *a, Real *b, Real *c) if(word_shift==-1L) return 0; /* Overflow */ if(b_pos == -1L) goto Assign_a; - round =((av + bv) >= HALF_BASE) ? 1 : 0; + mrv = av + bv; /* Most right val. Used for round. */ /* Just assign the last few digits of b to c because a has no */ /* corresponding digits to be added. */ @@ -2281,8 +2305,7 @@ VpAddAbs(Real *a, Real *b, Real *c) } if(c_pos) c->frac[c_pos - 1] += carry; - if(round) VpRdup(c); /* Roundup and normalize. */ - else VpNmlz(c); /* normalize the result */ + if(!VpInternalRound(c,0,(c->Prec>0)?a->frac[c->Prec-1]:0,mrv)) VpNmlz(c); goto Exit; Assign_a: @@ -2305,7 +2328,7 @@ static int VpSubAbs(Real *a, Real *b, Real *c) { U_LONG word_shift; - U_LONG round; + U_LONG mrv; U_LONG borrow; U_LONG ap; U_LONG bp; @@ -2330,10 +2353,10 @@ VpSubAbs(Real *a, Real *b, Real *c) if(b_pos == -1L) goto Assign_a; if(av >= bv) { - round =((av -= bv) >= HALF_BASE) ? 1 : 0; + mrv = av - bv; borrow = 0; } else { - round = 0; + mrv = 0; borrow = 1; } @@ -2395,8 +2418,8 @@ VpSubAbs(Real *a, Real *b, Real *c) } } if(c_pos) c->frac[c_pos - 1] -= borrow; - if(round) VpRdup(c); /* Round up and normalize */ - else VpNmlz(c); /* normalize the result */ + + if(!VpInternalRound(c,0,(c->Prec>0)?a->frac[c->Prec-1]:0,mrv)) VpNmlz(c); goto Exit; Assign_a: @@ -2454,7 +2477,7 @@ VpSetPTR(Real *a, Real *b, Real *c, U_LONG *a_pos, U_LONG *b_pos, U_LONG *c_pos, /* * a = xxxxxxAxxx * c = xxxxxx - * a_pos = | + * a_pos = | */ *a_pos = left_word; *av = a->frac[*a_pos]; /* av is 'A' shown in above. */ @@ -2544,11 +2567,11 @@ VpMult(Real *c, Real *a, Real *b) return 1; /* 0: 1 significant digit */ } - if((a->Prec == 1) &&(a->frac[0] == 1) &&(a->exponent == 1)) { + if(VpIsOne(a)) { VpAsgn(c, b, VpGetSign(a)); goto Exit; } - if((b->Prec == 1) &&(b->frac[0] == 1) &&(b->exponent == 1)) { + if(VpIsOne(b)) { VpAsgn(c, a, VpGetSign(b)); goto Exit; } @@ -2624,7 +2647,7 @@ VpMult(Real *c, Real *a, Real *b) VpNmlz(c); /* normalize the result */ if(w != NULL) { /* free work variable */ - VpAsgn(w, c, 2); + VpAsgn(w, c, 1); VpFree(c); c = w; } @@ -2675,8 +2698,7 @@ VpDivd(Real *c, Real *r, Real *a, Real *b) VpSetZero(r,VpGetSign(a)*VpGetSign(b)); goto Exit; } - - if((b->Prec == 1) &&(b->frac[0] == 1) &&(b->exponent == 1)) { + if(VpIsOne(b)) { /* divide by one */ VpAsgn(c, a, VpGetSign(b)); VpSetZero(r,VpGetSign(a)); @@ -2980,6 +3002,7 @@ Exit: return (int)val; } +#ifdef _DEBUG /* * cntl_chr ... ASCIIZ Character, print control characters * Available control codes: @@ -3082,6 +3105,7 @@ VPrint(FILE *fp, char *cntl_chr, Real *a) } return (int)nc; } +#endif /* _DEBUG */ static void VpFormatSt(char *psz,S_INT fFmt) @@ -3468,8 +3492,9 @@ VpDtoV(Real *m, double d) } m->Prec = ind_m + 1; m->exponent = ne; - if(val*((double)((S_INT)BASE)) >=(double)((S_INT)HALF_BASE)) VpRdup(m); - VpNmlz(m); + + if(!VpInternalRound(m,0,(m->Prec>0)?m->frac[m->Prec-1]:0, + (U_LONG)(val*((double)((S_INT)BASE))))) VpNmlz(m); Exit: #ifdef _DEBUG @@ -3551,8 +3576,8 @@ VpSqrt(Real *y, Real *x) Real *f = NULL; Real *r = NULL; S_LONG y_prec, f_prec; - S_LONG n; - S_LONG e; + S_LONG n; + S_LONG e; S_LONG prec; S_LONG nr; double val; @@ -3650,11 +3675,12 @@ Exit: /* * - * f = 1: round, 2:ceil, 3: floor + * f = 0: Round off/Truncate, 1: round up, 2:ceil, 3: floor, 4: Banker's rounding + * nf: digit position for operation. * */ VP_EXPORT void -VpRound(Real *y, Real *x, int sw, int f, int nf) +VpActiveRound(Real *y, Real *x, int f, int nf) { int n,i,j,ix,ioffset; U_LONG v; @@ -3665,35 +3691,41 @@ VpRound(Real *y, Real *x, int sw, int f, int nf) goto Exit; } - /* First,assign whole value */ - VpAsgn(y, x, sw); + /* First,assign whole value in truncation mode */ + VpAsgn(y, x, 1); /* 1 round off,2 round up */ nf += y->exponent*((int)BASE_FIG); /* ix: x->fraq[ix] contains round position */ ix = (nf + ((int)BASE_FIG))/((int)BASE_FIG)-1; if(ix<0 || ((U_LONG)ix)>=y->Prec) goto Exit; /* Unable to round */ ioffset = nf - ix*((int)BASE_FIG); for(j=ix+1;j<(int)y->Prec;++j) y->frac[j] = 0; - VpNmlz(y); + /* VpNmlz(y); */ v = y->frac[ix]; /* drop digits after pointed digit */ n = BASE_FIG - ioffset - 1; for(i=0;i<n;++i) v /= 10; div = v/10; v = v - div*10; - switch(f){ - case 1: /* Round */ - if(sw==2 && v>=5) { - ++div; - } + switch(f) { + case VP_COMP_MODE_TRUNCATE: /* Truncate/Round off */ + break; + case VP_COMP_MODE_ROUNDUP: /* Round up */ + if(v>=5) ++div; break; - case 2: /* ceil */ - if(v) { - if(VpGetSign(x)>0) ++div; - } + case VP_COMP_MODE_CEIL: /* ceil */ + if(v && (VpGetSign(x)>0)) ++div; + break; + case VP_COMP_MODE_FLOOR: /* floor */ + if(v && (VpGetSign(x)<0)) ++div; break; - case 3: /* floor */ - if(v) { - if(VpGetSign(x)<0) ++div; + case VP_COMP_MODE_EVEN: /* Banker's rounding */ + if(v>5) ++div; + else if(v==5) { + if(i==(BASE_FIG-1)) { + if(ix && (y->frac[ix-1]%2)) ++div; + } else { + if(div%2) ++div; + } } break; } @@ -3702,7 +3734,7 @@ VpRound(Real *y, Real *x, int sw, int f, int nf) y->frac[ix] = 0; if(ix) { VpNmlz(y); - VpRdup(y); + VpRdup(y,0); } else { VpSetOne(y); VpSetSign(y,VpGetSign(x)); @@ -3715,24 +3747,51 @@ VpRound(Real *y, Real *x, int sw, int f, int nf) Exit: #ifdef _DEBUG if(gfDebug) { - VPrint(stdout, "VpRound y=%\n", y); + VPrint(stdout, "VpActiveRound y=%\n", y); VPrint(stdout, " x=%\n", x); } #endif /*_DEBUG */ return; } +static int +VpInternalRound(Real *c,int ixDigit,U_LONG vPrev,U_LONG v) +{ + int f = 0; + v /= BASE1; + switch(gfCompMode) { + case VP_COMP_MODE_TRUNCATE: + break; + case VP_COMP_MODE_ROUNDUP: + if(v >= 5) f = 1; + break; + case VP_COMP_MODE_CEIL: /* ceil */ + if(v && (VpGetSign(c)>0)) f = 1; + break; + case VP_COMP_MODE_FLOOR: /* floor */ + if(v && (VpGetSign(c)<0)) f = 1; + break; + case VP_COMP_MODE_EVEN: /* Banker's rounding */ + if(v>5) f = 1; + else if(v==5 && vPrev%2) f = 1; + break; + } + if(f) VpRdup(c,ixDigit); /* round up */ + return f; +} + /* * Rounds up m(plus one to final digit of m). */ static int -VpRdup(Real *m) +VpRdup(Real *m,U_LONG ind_m) { - U_LONG ind_m, carry; - ind_m = m->Prec; + U_LONG carry; + + if(!ind_m) ind_m = m->Prec; + carry = 1; - while(carry > 0 && ind_m) { - --ind_m; + while(carry > 0 && (ind_m--)) { m->frac[ind_m] += carry; if(m->frac[ind_m] >= BASE) m->frac[ind_m] -= BASE; else carry = 0; @@ -3907,8 +3966,8 @@ VpPi(Real *y) VpAddSub(r, y, f, 1); /* r = y + f */ VpAsgn(y, r, 1); /* y = r */ - VpRdup(n); /* n = n + 1 */ - VpRdup(n); /* n = n + 1 */ + VpRdup(n,0); /* n = n + 1 */ + VpRdup(n,0); /* n = n + 1 */ if(VpIsZero(f)) break; } while((f->exponent > 0 || ((U_LONG)(-(f->exponent)) < y->MaxPrec)) && i1<nc @@ -3926,8 +3985,8 @@ VpPi(Real *y) VpAddSub(r, y, f, 1); /* r = y + f */ VpAsgn(y, r, 1); /* y = r */ - VpRdup(n); /* n = n + 1 */ - VpRdup(n); /* n = n + 1 */ + VpRdup(n,0); /* n = n + 1 */ + VpRdup(n,0); /* n = n + 1 */ if(VpIsZero(f)) break; } while((f->exponent > 0 || ((U_LONG)(-(f->exponent)) < y->MaxPrec)) && i2<nc @@ -3972,11 +4031,11 @@ VpExp1(Real *y) add = VpAlloc(p, "#1"); /* add = 1 */ VpSetOne(y); /* y = 1 */ - VpRdup(y); /* y = y + 1 */ + VpRdup(y,0); /* y = y + 1 */ i = 0; do { ++i; - VpRdup(n); /* n = n + 1 */ + VpRdup(n,0); /* n = n + 1 */ VpDivd(f, r, add, n); /* f = add/n(=1/n!) */ VpAsgn(add, f, 1); /* add = 1/n! */ VpAddSub(r, y, f, 1); @@ -4041,7 +4100,7 @@ VpExp(Real *y, Real *x) i = 0; do { ++i; - VpRdup(n); /* n = n + 1 */ + VpRdup(n,0); /* n = n + 1 */ VpDivd(div, r, x, n); /* div = x/n */ VpMult(c, z, div); /* c = x/(n-1)! * x/n */ VpAsgn(z, c, 1); /* z = x*n/n! */ @@ -4117,7 +4176,7 @@ VpSinCos(Real *psin,Real *pcos,Real *x) i = 0; do { ++i; - VpRdup(n); /* n = n + 1 */ + VpRdup(n,0); /* n = n + 1 */ VpDivd(div, r, x, n); /* div = x/n */ VpMult(c, z, div); /* c = x/(n-1)! * x/n */ VpAsgn(z, c, 1); /* z = x*n/n! */ diff --git a/ext/bigdecimal/bigdecimal.h b/ext/bigdecimal/bigdecimal.h index 8708d04b6f..3debb52826 100644 --- a/ext/bigdecimal/bigdecimal.h +++ b/ext/bigdecimal/bigdecimal.h @@ -32,7 +32,7 @@ extern "C" { #define S_INT int /* Exception codes */ -#define VP_EXCEPTION_ALL ((unsigned short)0xFFFF) +#define VP_EXCEPTION_ALL ((unsigned short)0x00FF) #define VP_EXCEPTION_INFINITY ((unsigned short)0x0001) #define VP_EXCEPTION_NaN ((unsigned short)0x0002) #define VP_EXCEPTION_UNDERFLOW ((unsigned short)0x0004) @@ -43,6 +43,14 @@ extern "C" { #define VP_EXCEPTION_OP ((unsigned short)0x0020) #define VP_EXCEPTION_MEMORY ((unsigned short)0x0040) +/* Computation mode */ +#define VP_COMP_MODE ((unsigned short)0x0100) +#define VP_COMP_MODE_TRUNCATE 0 +#define VP_COMP_MODE_ROUNDUP 1 +#define VP_COMP_MODE_CEIL 2 +#define VP_COMP_MODE_FLOOR 3 +#define VP_COMP_MODE_EVEN 4 + #define VP_SIGN_NaN 0 /* NaN */ #define VP_SIGN_POSITIVE_ZERO 1 /* Positive zero */ #define VP_SIGN_NEGATIVE_ZERO -1 /* Negative zero */ @@ -103,6 +111,10 @@ VP_EXPORT double VpGetDoubleNegZero(void); VP_EXPORT U_LONG VpGetPrecLimit(void); VP_EXPORT U_LONG VpSetPrecLimit(U_LONG n); +/* Computation mode */ +VP_EXPORT unsigned long VpGetCompMode(void); +VP_EXPORT unsigned long VpSetCompMode(unsigned long n); + VP_EXPORT int VpException(unsigned short f,char *str,int always); VP_EXPORT int VpIsNegDoubleZero(double v); VP_EXPORT U_LONG VpNumOfChars(Real *vp); @@ -123,14 +135,13 @@ VP_EXPORT void VpVtoD(double *d,S_LONG *e,Real *m); VP_EXPORT void VpDtoV(Real *m,double d); VP_EXPORT void VpItoV(Real *m,S_INT ival); VP_EXPORT int VpSqrt(Real *y,Real *x); -VP_EXPORT void VpRound(Real *y,Real *x,int sw,int f,int il); +VP_EXPORT void VpActiveRound(Real *y,Real *x,int f,int il); VP_EXPORT void VpFrac(Real *y,Real *x); VP_EXPORT int VpPower(Real *y,Real *x,S_INT n); VP_EXPORT void VpPi(Real *y); VP_EXPORT void VpExp1(Real *y); VP_EXPORT void VpExp(Real *y,Real *x); VP_EXPORT void VpSinCos(Real *psin,Real *pcos,Real *x); -VP_EXPORT int VPrint(FILE *fp,char *cntl_chr,Real *a); /* * ------------------ @@ -177,9 +188,11 @@ VP_EXPORT int VPrint(FILE *fp,char *cntl_chr,Real *a); #define VpSetPosInf(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_POSITIVE_INFINITE) #define VpSetNegInf(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NEGATIVE_INFINITE) #define VpSetInf(a,s) ( ((s)>0)?VpSetPosInf(a):VpSetNegInf(a) ) +#define VpIsOne(a) ((a->Prec==1)&&(a->frac[0]==1)&&(a->exponent==1)) #ifdef _DEBUG int VpVarCheck(Real * v); +VP_EXPORT int VPrint(FILE *fp,char *cntl_chr,Real *a); #endif /* _DEBUG */ #if defined(__cplusplus) diff --git a/ext/bigdecimal/bigdecimal_en.html b/ext/bigdecimal/bigdecimal_en.html index b8e9768f8f..04dd83a429 100644 --- a/ext/bigdecimal/bigdecimal_en.html +++ b/ext/bigdecimal/bigdecimal_en.html @@ -2,90 +2,27 @@ <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html"> <style type="text/css"><!-- -body { - color: #3f0f0f; - background: #fefeff; - margin-left: 2em; margin-right: 2em; -} -h1 { - color: #ffffff; - background-color: #3939AD; - border-color: #FF00FF; - width: 100%; - border-style: solid; - border-top-width: 0.1em; - border-bottom-width: 0.1em; - border-right: none; - border-left: none; - padding: 0.1em; - font-weight: bold; - font-size: 160%; - text-align: center; -} -h2 { - color: #00007f; - background-color: #e7e7ff; - border-color: #000094; - width: 100%; - border-style: solid; - border-left: none; - border-right: none; - border-top-width: 0.1em; - border-bottom-width: 0.1em; - padding: 0.1em; - font-weight: bold; - font-size: 110%; -} -h3 { - color: #00007f; - padding: 0.2em; - font-size: 110%; -} -h4, h5 { - color: #000000; - padding: 0.2em; - font-size: 100%; -} -table { - margin-top: 0.2em; margin-bottom: 0.2em; - margin-left: 2em; margin-right: 2em; -} -caption { - color: #7f0000; - font-weight: bold; -} -th { - background: #e7e7ff; - padding-left: 0.2em; padding-right: 0.2em; -} -td { - background: #f3f7ff; - padding-left: 0.2em; padding-right: 0.2em; -} -code { - color: #0000df; -} -dt { - margin-top: 0.2em; -} -li { - margin-top: 0.2em; +body { color: #3f0f0f; background: #fefeff; margin-left: 2em; margin-right: 2em;} +h1 { color: #ffffff; background-color: #3939AD; border-color: #FF00FF; width: 100%; border-style: solid; + border-top-width: 0.1em; border-bottom-width: 0.1em; border-right: none; border-left: none; + padding: 0.1em; font-weight: bold; font-size: 160%; text-align: center;} +h2 { color: #00007f; background-color: #e7e7ff; border-color: #000094; width: 100%; border-style: solid; border-le ft: none; border-right: none; border-top-width: 0.1em; border-bottom-width: 0.1em; padding: 0.1em; + font-weight: bold; font-size: 110%; } +h3 { color: #00007f; padding: 0.2em; font-size: 110%;} +h4, h5 { color: #000000; padding: 0.2em; font-size: 100%;} +table { margin-top: 0.2em; margin-bottom: 0.2em; margin-left: 2em; margin-right: 2em;} +caption { color: #7f0000; font-weight: bold;} +th { background: #e7e7ff; padding-left: 0.2em; padding-right: 0.2em;} +td { background: #f3f7ff; padding-left: 0.2em; padding-right: 0.2em;} +code { color: #0000df;} +dt { margin-top: 0.2em;} +li { margin-top: 0.2em;} pre -{ - BACKGROUND-COLOR: #d0d0d0; - BORDER-BOTTOM: medium none; - BORDER-LEFT: medium none; - BORDER-RIGHT: medium none; - BORDER-TOP: medium none; - LINE-HEIGHT: 100%; - MARGIN: 12px 12px 12px 12px; - PADDING-BOTTOM: 12px; - PADDING-LEFT: 12px; - PADDING-RIGHT: 12px; - PADDING-TOP: 12px; - WHITE-SPACE: pre; - WIDTH: 100% +{ BACKGROUND-COLOR: #d0d0d0; BORDER-BOTTOM: medium none; BORDER-LEFT: medium none; + BORDER-RIGHT: medium none; BORDER-TOP: medium none; LINE-HEIGHT: 100%; MARGIN: 12px 12px 12px 12px; + PADDING-BOTTOM: 12px; PADDING-LEFT: 12px; PADDING-RIGHT: 12px; PADDING-TOP: 12px; + WHITE-SPACE: pre; WIDTH: 100% } --></style> @@ -99,7 +36,6 @@ Using BigDecimal class, you can obtain any number of significant digits in compu For the details about Ruby see:<BR> <UL> <LI><A HREF="http://www.ruby-lang.org/en/">http://www.ruby-lang.org/en/</A>:Official Ruby page(English).</LI> -<LI><A HREF="http://ruby.freak.ne.jp/">http://ruby.freak.ne.jp/</A>:Ruby informations(Japanese).</LI> <LI><A HREF="http://kahori.com/ruby/ring/">http://kahori.com/ruby/ring/</A>:Mutually linked pages relating to Ruby(Japanese). </LI> </UL> @@ -126,7 +62,7 @@ NOTE:<BR> <A NAME="#INTRO"> <H2>Introduction</H2> Ruby already has builtin (variable length integer number) class Bignum. Using Bignum class,you can obtain - any integer value in magnitude. But, variable length floating number class is not yet built in. + any integer value in magnitude. But, variable length decimal number class is not yet built in. This is why I made variable length floating class BigDecimal. Feel free to send any comments or bug reports to me. <A HREF="mailto:shigeo@tinyforest.gr.jp">shigeo@tinyforest.gr.jp</A> @@ -155,16 +91,80 @@ not exactly but slightly excess memories will be allocated to newly created obje In 32 bits integer system,every 4 digits(in decimal) are computed simultaneously. This means the number of significant digits in BigDecimal is always a multiple of 4. +<H4><U>Class methods</U></H4> <UL> -<LI><B>new</B></LI><BR> +<LI><B>new</B></LI><BLOCKQUOTE> "new" method creates a new BigDecimal object.<BR> a=BigDecimal::new(s[,n])<BR> where:<BR> s: Initial value string.<BR> n: Maximum number of significant digits of a. n must be a Fixnum object. If n is omitted or is equal to 0,then the maximum number of significant digits of a is determined from the length of s. +</BLOCKQUOTE> + +<LI><B>mode</B></LI><BLOCKQUOTE> +mode method controls BigDecimal computation.Following usage are defined.<BR> +<P><B>[EXCEPTION control]</B><P> +Actions when computation results NaN or Infinity can be defined as follows. +<P> +<BLOCKQUOTE> +f = BigDecimal::mode(BigDecimal::EXCEPTION_NaN,flag)<BR> +f = BigDecimal::mode(BigDecimal::EXCEPTION_INFINITY,flag)<BR> +f = BigDecimal::mode(BigDecimal::EXCEPTION_UNDERFLOW,flag)<BR> +f = BigDecimal::mode(BigDecimal::EXCEPTION_OVERFLOW,flag)<BR> +f = BigDecimal::mode(BigDecimal::EXCEPTION_ZERODIVIDE,flag)<BR> +f = BigDecimal::mode(BigDecimal::EXCEPTION_ALL,flag)<BR> +</BLOCKQUOTE> +EXCEPTION_NaN controls the execution when computation results to NaN.<BR> +EXCEPTION_INFINITY controls the execution when computation results to Infinity(±Infinity).<BR> +EXCEPTION_UNDERFLOW controls the execution when computation underflows.<BR> +EXCEPTION_OVERFLOW controls the execution when computation overflows.<BR> +EXCEPTION_ZERODIVIDE controls the execution when zero-division occures.<BR> +EXCEPTION_ALL controls the execution for any exception defined occures.<BR> +If the flag is true,then the relating exception is thrown.<BR> +No exception is thrown when the flag is false(default) and computation +continues with the result:<BR> +<BLOCKQUOTE> +EXCEPTION_NaN results to NaN<BR> +EXCEPTION_INFINITY results to +Infinity or -Infinity<BR> +EXCEPTION_UNDERFLOW results to 0.<BR> +EXCEPTION_OVERFLOW results to +Infinity or -Infinity<BR> +EXCEPTION_ZERODIVIDE results to +Infinity or -Infinity<BR> +</BLOCKQUOTE> +EXCEPTION_INFINITY,EXCEPTION_OVERFLOW, and EXCEPTION_ZERODIVIDE are + currently the same.<BR> +The return value of mode method is the previous value set.<BR> +nil is returned if any argument is wrong.<BR> +Suppose the return value of the mode method is f,then + f & BigDecimal::EXCEPTION_NaN !=0 means EXCEPTION_NaN is set to on. +<P> +<B>[ROUND error control]</B><P> +Rounding operation can be controlled as: +<BLOCKQUOTE> +f = BigDecimal::mode(BigDecimal::COMP_MODE,flag) +</BLOCKQUOTE> +where flag must be one of: +<TABLE> +<TR><TD>COMP_MODE_TRUNCATE</TD><TD>truncate</TD></TR> +<TR><TD>COMP_MODE_ROUNDUP</TD><TD>roundup,default</TD></TR> +<TR><TD>COMP_MODE_CEIL</TD><TD>ceil</TD></TR> +<TR><TD>COMP_MODE_FLOOR</TD><TD>floor</TD></TR> +<TR><TD>COMP_MODE_EVEN</TD><TD>Banker's rounding</TD></TR> +</TABLE> +nil is returned if any argument is illegal.<BR> +The digit location for rounding operation can not be specified by mode method, +use truncate/roundup/ceil/floor mthods for each instance instead. + +</BLOCKQUOTE> -<LI><B>double_fig</B></LI><BR> +<LI><B>limit[(n)]</B></LI><BLOCKQUOTE> +Limits the maximum digits that the newly created BigDecimal objects can hold +never exceed n. Returns maximum value before set. +Zero,the default value,means no upper limit.<BR> +mf = BigDecimal::limit(n)<BR> +</BLOCKQUOTE> + +<LI><B>double_fig</B></LI><BLOCKQUOTE> double_fig is a class method which returns the number of digits the Float class can have. <CODE><PRE> @@ -180,71 +180,71 @@ double_fig is: v /= 10; } </PRE></CODE> +</BLOCKQUOTE> -<LI><B>prec</B></LI><BR> -r,m = a.prec<BR> -where r is the number of significant digits of a, -m is the maximum number of significant digits a can hold.<br> -<CODE><PRE> - require "bigdecimal" - a = BigDecimal.new("0.12345") - p a.prec # ==> [8, 12] - b = BigDecimal.new("0.1234500000000") - p b.prec # ==> [8, 20] - c = BigDecimal.new("0.12345",20) - p c.prec # ==> [8, 24] -</PRE></CODE> -r and m are always the multiple of log10(BigDecimal::BASE). +<LI><B>BASE</B></LI><BLOCKQUOTE> +Base value used in the BigDecimal calculation. +On 32 bits integer system,the value of BASE is 10000.<BR> +b = BigDecimal::BASE<BR> +</BLOCKQUOTE> + +<LI><B>E</B></LI><BLOCKQUOTE> +e = BigDecimal::E(n)<BR> +where e(=2.718281828....) is the base value of natural logarithm.<BR> +n specifies the length of significant digits of e. + +</BLOCKQUOTE> +<LI><B>PI</B></LI><BLOCKQUOTE> +e = BigDecimal::PI(n)<BR> +returns at least n digits of the ratio of the circumference of a circle to its diameter +(pi=3.14159265358979....) using J.Machin's formula.<BR> +</BLOCKQUOTE> +</UL> -<LI><B>+</B></LI><BR> +<H4><U>Instance methods</U></H4> +<UL> +<LI><B>+</B></LI><BLOCKQUOTE> addition(c = a + b)<BR> For the resulting number of significant digits of c,see <A HREF="#PREC">Resulting number of significant digits</A>. -<LI><B>-</B></LI><BR> +</BLOCKQUOTE> +<LI><B>-</B></LI><BLOCKQUOTE> subtraction (c = a - b) or negation (c = -a)<BR> For the resulting number of significant digits of c,see <A HREF="#PREC">Resulting number of significant digits</A>. -<LI><B>*</B></LI><BR> +</BLOCKQUOTE> +<LI><B>*</B></LI><BLOCKQUOTE> multiplication(c = a * b)<BR> For the resulting number of significant digits of c,see <A HREF="#PREC">Resulting number of significant digits</A>. -<LI><B>/</B></LI><BR> +</BLOCKQUOTE> +<LI><B>/</B></LI><BLOCKQUOTE> division(c = a / b)<BR> For the resulting number of significant digits of c,see <A HREF="#PREC">Resulting number of significant digits</A>. +</BLOCKQUOTE> -<LI><B>assign</B></LI><BR> -c = a.assign(n,f)<BR> -assigns the value of a to c.<BR> -n is the number of significant digits of resulting c.<BR> -If f > 0,then a is assigned to c.<BR> -If f < 0,then -a is assigned to c.<BR> -The absolute value of f (|f|) must be 1 or 2. -If |f|=2,then proper round operation over c is performed,when the maximum -number of significant digits of c is less than current -number of significant digits of a. -If |f|=1 then extra digits are discarded when the maximum -number of significant digits of c is less than current -number of significant digits of a. - -<LI><B>add</B></LI><BR> +<LI><B>add</B></LI><BLOCKQUOTE> c = a.add(b,n)<BR> c = a.add(b,n) performs c = a + b. If n is less than the actual significant digits of a + b, then c is rounded properly. -<LI><B>sub</B></LI><BR> +</BLOCKQUOTE> +<LI><B>sub</B></LI><BLOCKQUOTE> c = a.sub(b,n)<BR> c = a.sub(b,n) performs c = a - b. If n is less than the actual significant digits of a - b, then c is rounded properly. -<LI><B>mult</B></LI><BR> +</BLOCKQUOTE> +<LI><B>mult</B></LI><BLOCKQUOTE> c = a.mult(b,n)<BR> c = a.mult(b,n) performs c = a * b. If n is less than the actual significant digits of a * b, then c is rounded properly. -<LI><B>div</B></LI><BR> +</BLOCKQUOTE> +<LI><B>div</B></LI><BLOCKQUOTE> c,r = a.div(b,n)<BR> c,r = a.div(b,n) performs c = a / b, r is the residue of a / b. If necessary,the divide operation continues to n digits which c @@ -253,169 +253,154 @@ Unlike the divmod method,c is not always an integer. c is never rounded,and the equation a = c*b + r is always valid unless c is NaN or Infinity. -<LI><B>%</B></LI><BR> +</BLOCKQUOTE> +<LI><B>%</B></LI><BLOCKQUOTE> r = a%b <BR> is the same as:<BR> r = a-((a/b).floor)*b<BR> -<LI><B>fix</B></LI><BR> +</BLOCKQUOTE> +<LI><B>fix</B></LI><BLOCKQUOTE> c = a.fix<BR> returns integer part of a.<BR> -<LI><B>frac</B></LI><BR> +</BLOCKQUOTE> +<LI><B>frac</B></LI><BLOCKQUOTE> c = a.frac<BR> returns fraction part of a.<BR> -<LI><B>floor[(n)]</B></LI><BR> +</BLOCKQUOTE> +<LI><B>floor[(n)]</B></LI><BLOCKQUOTE> c = a.floor<BR> -returns the maximum integer value (in BigDecimal) which is less than or equal to a.<BR> -As shown in the following example,an optional integer argument (n) specifying the position -of 'floor'ed digit can be given. -If n> 0,then the (n+1)th digit counted from the decimal point in fraction part is 'floor'ed. -If n<0,then the n-th digit counted from the decimal point in integer part is 'floor'ed.<BR> +returns the maximum integer value (in BigDecimal) which is less than or equal to a. +<PRE><CODE> + c = BigDecimal("1.23456").floor # ==> 1 + c = BigDecimal("-1.23456").floor # ==> -2 +</CODE></PRE> -c = BigDecimal::new("1.23456")<BR> -d = c.floor(4) # d = 1.2345<BR> -c = BigDecimal::new("15.23456")<BR> -d = c.floor(-1) # d = 10.0<BR> +As shown in the following example,an optional integer argument (n) specifying the position +of the target digit can be given.<BR> +If n> 0,then the (n+1)th digit counted from the decimal point in fraction part is processed(resulting number of fraction part digits is less than or equal to n).<BR> +If n<0,then the n-th digit counted from the decimal point in integer part is processed(at least n 0's are placed from the decimal point to left). +<PRE><CODE> + c = BigDecimal::new("1.23456").floor(4) # ==> 1.2345 + c = BigDecimal::new("15.23456").floor(-1) # ==> 10.0 +</CODE></PRE> -<LI><B>ceil[(n)]</B></LI><BR> +</BLOCKQUOTE> +<LI><B>ceil[(n)]</B></LI><BLOCKQUOTE> c = a.ceil<BR> -returns the minimum integer value (in BigDecimal) which is greater than or equal to a.<BR> -As shown in the following example,an optional integer argument (n) specifying the position -of 'ceil'ed digit can be given. -If n>0,then the (n+1)th digit counted from the decimal point in fraction part is 'ceil'ed. -If n<0,then the n-th digit counted from the decimal point in integer part is 'ceil'ed.<BR> +returns the minimum integer value (in BigDecimal) which is greater than or equal to a. +<PRE><CODE> + c = BigDecimal("1.23456").ceil # ==> 2 + c = BigDecimal("-1.23456").ceil # ==> -1 +</CODE></PRE> -c = BigDecimal::new("1.23456")<BR> -d = c.ceil(4) # d = 1.2346<BR> -c = BigDecimal::new("15.23456")<BR> -d = c.ceil(-1) # d = 20.0<BR> +As shown in the following example,an optional integer argument (n) specifying the position +of the target digit can be given.<BR> +If n>0,then the (n+1)th digit counted from the decimal point in fraction part is processed(resulting number of fraction part digits is less than or equal to n).<BR> +If n<0,then the n-th digit counted from the decimal point in integer part is processed(at least n 0's are placed from the decimal point to left). +<PRE><CODE> + c = BigDecimal::new("1.23456").ceil(4) # ==> 1.2346 + c = BigDecimal::new("15.23456").ceil(-1) # ==> 20.0 +</CODE></PRE> -<LI><B>round[(n)]</B></LI><BR> +</BLOCKQUOTE> +<LI><B>round[(n[,b])]</B></LI><BLOCKQUOTE> c = a.round<BR> -round off a to the nearest 1.<BR> +round a to the nearest 1.<BR> +<PRE><CODE> + c = BigDecimal("1.23456").round # ==> 1 + c = BigDecimal("-1.23456").round # ==> -1 +</CODE></PRE> + As shown in the following example,an optional integer argument (n) specifying the position -of rounded digit can be given. -If n>0,then the (n+1)th digit counted from the decimal point in fraction part is rounded. -If n<0,then the n-th digit counted from the decimal point in integer part is rounded.<BR> +of the target digit can be given.<BR> +If n>0,then the (n+1)th digit counted from the decimal point in fraction part is processed(resulting number of fraction part digits is less than or equal to n).<BR> +If n<0,then the n-th digit counted from the decimal point in integer part is processed(at least n 0's are placed from the decimal point to left). +<PRE><CODE> +c = BigDecimal::new("1.23456").round(4) # ==> 1.2346 +c = BigDecimal::new("15.23456").round(-1) # ==> 20.0 +</CODE></PRE> -c = BigDecimal::new("1.23456")<BR> -d = c.round(4) # d = 1.235 <BR> -c = BigDecimal::new("15.23456")<BR> -d = c.round(-1) # d = 20.0<BR> +If the second optional argument b is given with the non-zero value(default is zero) then +so called Banker's rounding is performed.<BR> +Suppose the digit p is to be rounded,then:<BR> + If p<5 then p is truncated<BR> + If p>5 then p is rounded up<BR> + If p is 5 then round up operation is taken only when the left hand side digit of p is odd. +<PRE><CODE> +c = BigDecimal::new("1.23456").round(3,1) # ==> 1.234 +c = BigDecimal::new("1.23356").round(3,1) # ==> 1.234 +</CODE></PRE> -<LI><B>truncate[(n)]</B></LI><BR> +</BLOCKQUOTE> +<LI><B>truncate[(n)]</B></LI><BLOCKQUOTE> c = a.truncate<BR> truncate a to the nearest 1.<BR> As shown in the following example,an optional integer argument (n) specifying the position -of truncated digit can be given. -If n>0,then the (n+1)th digit counted from the decimal point in fraction part is truncated. -If n<0,then the n-th digit counted from the decimal point in integer part is truncated.<BR> +of the target digit can be given.<BR> +If n>0,then the (n+1)th digit counted from the decimal point in fraction part is processed(resulting number of fraction part digits is less than or equal to n).<BR> +If n<0,then the n-th digit counted from the decimal point in integer part is processed(at least n 0's are placed from the decimal point to left). -c = BigDecimal::new("1.23456")<BR> -d = c.truncate(4) # d = 1.2345<BR> -c = BigDecimal::new("15.23456")<BR> -d = c.truncate(-1) # d = 10.0<BR> +<PRE><CODE> +c = BigDecimal::new("1.23456").truncate(4) # ==> 1.2345 +c = BigDecimal::new("15.23456").truncate(-1) # ==> 10.0 +</CODE></PRE> -<LI><B>divmod</B></LI><BR> +</BLOCKQUOTE> +<LI><B>divmod</B></LI><BLOCKQUOTE> c,r = a.divmod(b) # a = c*b + r<BR> returns the quotient and remainder of a/b.<BR> a = c * b + r is always satisfied.<BR> -where c is the integer sutisfying +where c is the integer satisfying c = (a/b).floor <BR> and,therefore r = a - c*b<BR> -<LI><B>remainder</B></LI><BR> +</BLOCKQUOTE> +<LI><B>remainder</B></LI><BLOCKQUOTE> r=a.remainder(b)<BR> returns the remainder of a/b.<BR> -where c is the integer sutisfying +where c is the integer satisfying c = (a/b).fix <BR> and,therefore: r = a - c*b<BR> -<LI><B>abs</B></LI><BR> +</BLOCKQUOTE> +<LI><B>abs</B></LI><BLOCKQUOTE> c = a.abs<BR> returns an absolute value of a.<BR> -<LI><B>to_i</B></LI><BR> +</BLOCKQUOTE> +<LI><B>to_i</B></LI><BLOCKQUOTE> changes a to an integer.<BR> i = a.to_i<BR> i becomes to Fixnum or Bignum. -IF a is Infinity or NaN,then i becomes to nil. +If a is Infinity or NaN,then i becomes to nil. -<LI><B>to_s[(n)]</B></LI><BR> +</BLOCKQUOTE> +<LI><B>to_s[(n)]</B></LI><BLOCKQUOTE> converts to string(results look like "0.xxxxxEn").<BR> s = a.to_s<BR> If n is given,then a space is inserted after every n digits for readability.<BR> s = a.to_s(n) -<LI><B>exponent</B></LI><BR> +</BLOCKQUOTE> +<LI><B>exponent</B></LI><BLOCKQUOTE> returns an integer holding exponent value of a.<BR> n = a.exponent <BR> means a = 0.xxxxxxx*10**n. -<LI><B>to_f</B></LI><BR> +</BLOCKQUOTE> +<LI><B>to_f</B></LI><BLOCKQUOTE> same as dup method. creates a new BigDecimal object having same value. +</BLOCKQUOTE> -<LI><B>E</B></LI><BR> -e = BigDecimal::E(n)<BR> -where e(=2.718281828....) is the base value of natural logarithm.<BR> -n specifies the length of significant digits of e. - -<LI><B>PI</B></LI><BR> -e = BigDecimal::PI(n)<BR> -returns at least n digits of the ratio of the circumference of a circle to its dirmeter -(pi=3.14159265358979....) using J.Machin's formula.<BR> - -<LI><B>BASE</B></LI><BR> -Base value used in the BigDecimal calculation. -On 32 bit integer system,the value of BASE is 10000.<BR> -b = BigDecimal::BASE<BR> - -<LI><B>mode</B></LI><BR> -mode method controls BigDecimal computation. -Following usage are defined.<BR> - -f = BigDecimal::mode(BigDecimal::EXCEPTION_NaN,flag)<BR> -f = BigDecimal::mode(BigDecimal::EXCEPTION_INFINITY,flag)<BR> -f = BigDecimal::mode(BigDecimal::EXCEPTION_UNDERFLOW,flag)<BR> -f = BigDecimal::mode(BigDecimal::EXCEPTION_OVERFLOW,flag)<BR> -f = BigDecimal::mode(BigDecimal::EXCEPTION_ZERODIVIDE,flag)<BR> -f = BigDecimal::mode(BigDecimal::EXCEPTION_ALL,flag)<BR> - -EXCEPTION_NaN controls the execution once computation results to NaN. -EXCEPTION_INFINITY controls the execution once computation results to Infinity(±Infinity). -EXCEPTION_UNDERFLOW controls the execution once computation underflows. -EXCEPTION_OVERFLOW controls the execution once computation overflows. -EXCEPTION_ZERODIVIDE controls the execution once zero-division occures. -EXCEPTION_ALL controls the execution for any exception defined occures. -If the flag is true,then the relating exception is thrown. -No exception is thrown when the flag is false(default) and computation -continues with the result:<BR> -EXCEPTION_NaN results to NaN<BR> -EXCEPTION_INFINITY results to +Infinity or -Infinity<BR> -EXCEPTION_UNDERFLOW results to 0.<BR> -EXCEPTION_OVERFLOW results to +Infinity or -Infinity<BR> -EXCEPTION_ZERODIVIDE results to +Infinity or -Infinity<BR> -EXCEPTION_INFINITY,EXCEPTION_OVERFLOW, and EXCEPTION_ZERODIVIDE are - currently the same.<BR> -The return value of mode method is the value set. -Suppose the return value of the mode method is f,then - f & BigDecimal::EXCEPTION_NaN !=0 means EXCEPTION_NaN is set to on. -If the value of the argument flag is other than nil,true nor false then -current mode status is returned. - -<LI><B>limit[(n)]</B></LI><BR> -Limits the maximum digits that the newly created BigDecimal objects can hold -never exceed n. Returns maximum value before set. -Zero,the default value,means no upper limit.<BR> -mf = BigDecimal::limit(n)<BR> - -<LI><B>sign</B></LI><BR> -returns the 'attribute'. +</BLOCKQUOTE> +<LI><B>sign</B></LI><BLOCKQUOTE> +returns the 'attribute' of a. n = a.sign <BR> where the value of n means that a is:<BR> n = BigDecimal::SIGN_NaN(0) : a is NaN<BR> @@ -427,28 +412,42 @@ n = BigDecimal::SIGN_POSITIVE_INFINITE(3) : a is +Infinity<BR> n = BigDecimal::SIGN_NEGATIVE_INFINITE(-3) : a is -Infinity<BR> The value in () is the actual value,see (<A HREF="#STRUCT">Internal structure</A>.<BR> -<LI><B>nan?</B></LI><BR> +</BLOCKQUOTE> +<LI><B>nan?</B></LI><BLOCKQUOTE> a.nan? returns True when a is NaN. -<LI><B>infinite?</B></LI><BR> -a.infinite? returns True when a is +∞ or -∞. +</BLOCKQUOTE> +<LI><B>infinite?</B></LI><BLOCKQUOTE> +a.infinite? returns 1 when a is +∞,-1 when a is -∞, nil otherwise. + +</BLOCKQUOTE> +<LI><B>finite?</B></LI><BLOCKQUOTE> +a.finite? returns true when a is neither ∞ nor NaN. +</BLOCKQUOTE> -<LI><B>finite?</B></LI><BR> -a.finite? returns True when a is neither ∞ nor NaN. +<LI><B>zero?</B></LI><BLOCKQUOTE> +c = a.zero?<BR> +returns true if a is equal to 0,otherwise returns false<BR> +</BLOCKQUOTE> +<LI><B>nonzero?</B></LI><BLOCKQUOTE> +c = a.nonzero?<BR> +returns nil if a is 0,otherwise returns a itself.<BR> +</BLOCKQUOTE> -<LI><B>to_parts</B></LI><BR> +<LI><B>split</B></LI><BLOCKQUOTE> decomposes a BigDecimal value to 4 parts. All 4 parts are returned as an array.<BR> Parts consist of a sign(0 when the value is NaN,+1 for positive and -1 for negative value), a string representing fraction part,base value(always 10 currently),and an integer(Fixnum) for exponent respectively. -a=BigDecimal::new("3.14159265",10)<BR> -f,x,y,z = a.to_parts<BR> +a=BigDecimal::new("3.14159265")<BR> +f,x,y,z = a.split<BR> where f=+1,x="314159265",y=10 and z=1<BR> therefore,you can translate BigDecimal value to Float as:<BR> s = "0."+x<BR> b = f*(s.to_f)*(y**z)<BR> -<LI><B>inspect</B></LI><BR> +</BLOCKQUOTE> +<LI><B>inspect</B></LI><BLOCKQUOTE> is used for debugging output.<BR> p a=BigDecimal::new("3.14",10)<BR> should produce output like "#<0x112344:'0.314E1',4(12)%gt;". @@ -457,38 +456,44 @@ where "0x112344" is the address, and 12 is the maximum number of the significant digits the object can hold. -<LI><B>dup</B></LI><BR> +</BLOCKQUOTE> +<LI><B>dup</B></LI><BLOCKQUOTE> creates a new BigDecimal object having same value. -<LI><B>sqrt</B></LI><BR> +</BLOCKQUOTE> +<LI><B>sqrt</B></LI><BLOCKQUOTE> c = a.sqrt(n)<BR> computes square root value of a with significant digit number n at least.<BR> -<LI><B>sincos</B></LI><BR> +</BLOCKQUOTE> +<LI><B>sincos</B></LI><BLOCKQUOTE> computes and returns sine and cosine value of a with significant digit number n at least.<BR> sin,cos = a.sincos(n)<BR> Computation may return bad results unless |a|<2*3.1415..... -<LI><B>exp</B></LI><BR> +</BLOCKQUOTE> +<LI><B>exp</B></LI><BLOCKQUOTE> c = a.exp(n)<BR> computes the base of natural logarithm value(e=2.718281828....) powered by a with significant digit number n at least.<BR> -<LI><B>power</B></LI><BR> +</BLOCKQUOTE> +<LI><B>**</B></LI><BLOCKQUOTE> +c = a ** n<BR> +returns the value of a powered by n. +n must be an integer.<BR> + +</BLOCKQUOTE> +<LI><B>power</B></LI><BLOCKQUOTE> +The same as ** method.<BR> c = a.power(n)<BR> returns the value of a powered by n(c=a**n). n must be an integer.<BR> -<LI><B>zero?</B></LI><BR> -c = a.zero?<BR> -returns true if a is equal to 0,otherwise returns false<BR> - -<LI><B>nonzero?</B></LI><BR> -c = a.nonzero?<BR> -returns false if a is 0,otherwise returns a itself.<BR> - -<LI><B><=></B></LI><BR> +</BLOCKQUOTE> +<LI><B><=></B></LI><BLOCKQUOTE> c = a <=> b <BR> returns 0 if a==b,1 if a > b,and returns -1 if a < b.<BR> +</BLOCKQUOTE> </UL> Following methods need no explanation.<BR> diff --git a/ext/bigdecimal/bigdecimal_ja.html b/ext/bigdecimal/bigdecimal_ja.html index efd4228d9a..56bebaa863 100644 --- a/ext/bigdecimal/bigdecimal_ja.html +++ b/ext/bigdecimal/bigdecimal_ja.html @@ -2,90 +2,30 @@ <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=Shift_JIS"> <style type="text/css"><!-- -body { - color: #3f0f0f; - background: #fefeff; - margin-left: 2em; margin-right: 2em; +body { color: #3f0f0f; background: #fefeff; margin-left: 2em; margin-right: 2em;} +h1 { color: #ffffff; background-color: #3939AD; border-color: #FF00FF; width: 100%; + border-style: solid; border-top-width: 0.1em; border-bottom-width: 0.1em; border-right: none; + border-left: none; padding: 0.1em; font-weight: bold; font-size: 160%; text-align: center; } -h1 { - color: #ffffff; - background-color: #3939AD; - border-color: #FF00FF; - width: 100%; - border-style: solid; - border-top-width: 0.1em; - border-bottom-width: 0.1em; - border-right: none; - border-left: none; +h2 { color: #00007f; background-color: #e7e7ff; border-color: #000094; width: 100%; + border-style: solid; border-left: none; border-right: none; border-top-width: 0.1em; border-bottom-width: 0.1em; padding: 0.1em; - font-weight: bold; - font-size: 160%; - text-align: center; -} -h2 { - color: #00007f; - background-color: #e7e7ff; - border-color: #000094; - width: 100%; - border-style: solid; - border-left: none; - border-right: none; - border-top-width: 0.1em; - border-bottom-width: 0.1em; - padding: 0.1em; - font-weight: bold; - font-size: 110%; -} -h3 { - color: #00007f; - padding: 0.2em; - font-size: 110%; -} -h4, h5 { - color: #000000; - padding: 0.2em; - font-size: 100%; -} -table { - margin-top: 0.2em; margin-bottom: 0.2em; - margin-left: 2em; margin-right: 2em; -} -caption { - color: #7f0000; - font-weight: bold; -} -th { - background: #e7e7ff; - padding-left: 0.2em; padding-right: 0.2em; -} -td { - background: #f3f7ff; - padding-left: 0.2em; padding-right: 0.2em; -} -code { - color: #0000df; -} -dt { - margin-top: 0.2em; -} -li { - margin-top: 0.2em; + font-weight: bold; font-size: 110%; } +h3 { color: #00007f; padding: 0.2em; font-size: 110%;} +h4, h5 { color: #000000; padding: 0.2em; font-size: 100%;} +table { margin-top: 0.2em; margin-bottom: 0.2em; margin-left: 2em; margin-right: 2em;} +caption { color: #7f0000; font-weight: bold;} +th { background: #e7e7ff; padding-left: 0.2em; padding-right: 0.2em;} +td { background: #f3f7ff; padding-left: 0.2em; padding-right: 0.2em;} +code { color: #0000df;} +dt { margin-top: 0.2em;} +li { margin-top: 0.2em;} pre -{ - BACKGROUND-COLOR: #d0d0d0; - BORDER-BOTTOM: medium none; - BORDER-LEFT: medium none; - BORDER-RIGHT: medium none; - BORDER-TOP: medium none; - LINE-HEIGHT: 100%; - MARGIN: 12px 12px 12px 12px; - PADDING-BOTTOM: 12px; - PADDING-LEFT: 12px; - PADDING-RIGHT: 12px; - PADDING-TOP: 12px; - WHITE-SPACE: pre; - WIDTH: 100% +{ BACKGROUND-COLOR: #d0d0d0; BORDER-BOTTOM: medium none; BORDER-LEFT: medium none; + BORDER-RIGHT: medium none; BORDER-TOP: medium none; LINE-HEIGHT: 100%; MARGIN: 12px 12px 12px 12px; + PADDING-BOTTOM: 12px; PADDING-LEFT: 12px; PADDING-RIGHT: 12px; PADDING-TOP: 12px; + WHITE-SPACE: pre; WIDTH: 100% } --></style> @@ -99,7 +39,6 @@ BigDecimal はオブジェクト指向の強力なスクリプト言語である Ruby に可変長浮動小数 Ruby についての詳しい内容は以下のURLを参照してください。 <UL> <LI><A HREF="http://www.ruby-lang.org/ja/">http://www.ruby-lang.org/ja/</A>:Ruby公式ページ</LI> -<LI><A HREF="http://ruby.freak.ne.jp/">http://ruby.freak.ne.jp/</A>:Rubyに関する情報ページ</LI> <LI><A HREF="http://kahori.com/ruby/ring/">http://kahori.com/ruby/ring/</A>:Rubyに関するページを辿れます</LI> </UL> <hr> @@ -160,8 +99,9 @@ c=a+b 例えば32ビットのシステムでは10進で4桁毎に計算します。従って、現状では、 内部の「有効桁数」は4の倍数となっています。 +<H4><U>クラスメソッド</U></H4> <UL> -<LI>new</LI><BR> +<LI><B>new</B></LI><BLOCKQUOTE> 新しい BigDecimal オブジェクトを生成します。<BR> a=BigDecimal::new(s[,n])<BR> s は初期値を文字列で指定します. @@ -169,50 +109,151 @@ n は必要な有効桁数(a の最大有効桁数)を整数で指定します。 n が 0 または省略されたときは、n の値は s の有効桁数とみなされます。 s の有効桁数より n が小さいときも n=0 のときと同じです。 a の最大有効桁数は n より若干大い値が採用されます。 -<LI>+</LI><BR> +</BLOCKQUOTE> + +<LI><B>mode</B></LI><BLOCKQUOTE> +BigDecimalの実行結果を制御します。以下の使用方法が定義されています。 +<P> +<B>[例外処理]</B><P> +計算結果が非数(NaN)やゼロによる除算になったときの処理を定義することができます。 +<BLOCKQUOTE> +f = BigDecimal::mode(BigDecimal::EXCEPTION_NaN,flag)<BR> +f = BigDecimal::mode(BigDecimal::EXCEPTION_INFINITY,flag)<BR> +f = BigDecimal::mode(BigDecimal::EXCEPTION_UNDERFLOW,flag)<BR> +f = BigDecimal::mode(BigDecimal::EXCEPTION_OVERFLOW,flag)<BR> +f = BigDecimal::mode(BigDecimal::EXCEPTION_ZERODIVIDE,flag)<BR> +f = BigDecimal::mode(BigDecimal::EXCEPTION_ALL,flag)<BR> +</BLOCKQUOTE> + +EXCEPTION_NaN は結果が NaN になったときの指定です。<BR> +EXCEPTION_INFINITY は結果が無限大(±Infinity)になったときの指定です。<BR> +EXCEPTION_UNDERFLOW は指数部がアンダーフローするときの指定です。<BR> +EXCEPTION_OVERFLOW は指数部がオーバーフローするときの指定です。<BR> +EXCEPTION_ZERODIVIDE はゼロによる割り算を実行したときの指定です。<BR> +EXCEPTION_ALL は、可能な全てに対して一括して設定するときに使用します。<BR><BR> + +flag が true のときは、指定した状態になったときに例外を発行するようになります。<BR> +flag が false(デフォルト)なら、例外は発行されません。計算結果は以下のようになります。<BR> +<BLOCKQUOTE> +EXCEPTION_NaN のとき、非数(NaN)<BR> +EXCEPTION_INFINITY のとき、無限(+ or -Infinity)<BR> +EXCEPTION_UNDERFLOW のとき、ゼロ<BR> +EXCEPTION_OVERFLOW のとき、+Infinity か -Infinity<BR> +EXCEPTION_ZERODIVIDE のとき、+Infinity か -Infinity<BR> +</BLOCKQUOTE> +EXCEPTION_INFINITY、EXCEPTION_OVERFLOW、EXCEPTION_ZERODIVIDE +は今のところ同じです。<BR> +戻り値は、設定前の値です。「値」の意味は、例えば +BigDecimal::EXCEPTION_NaNと「値」の & が ゼロ以外ならば +EXCEPTION_NaNが設定されているという意味です。<BR> +引数に正しくないものが指定された場合は nil が返ります。 + +<P> +<B>[丸め処理指定]</B><P> +計算途中の丸め操作の指定ができます。 +<BLOCKQUOTE> +f = BigDecimal::mode(BigDecimal::COMP_MODE,flag) +</BLOCKQUOTE> +の形式で指定します。<BR> +ここで、flag は以下の一つを指定します。 +<TABLE> +<TR><TD>COMP_MODE_TRUNCATE</TD><TD>全て切り捨てます(truncate)。</TD></TR> +<TR><TD>COMP_MODE_ROUNDUP</TD><TD>四捨五入します(roundup、デフォルト)。</TD></TR> +<TR><TD>COMP_MODE_CEIL</TD><TD>数値の大きい方に繰り上げます(ceil)。</TD></TR> +<TR><TD>COMP_MODE_FLOOR</TD><TD>数値の小さい方に繰り下げます(floor)。</TD></TR> +<TR><TD>COMP_MODE_EVEN</TD><TD>四捨六入します。5の時は上位1桁が奇数の時のみ繰り上げます(Banker's rounding)。</TD></TR> +</TABLE> +戻り値は指定前の flag の値です。 +引数に正しくないものが指定された場合は nil が返ります。<BR> +mode メソッドでは丸め操作の位置をユーザが指定することはできません。 +丸め操作と位置を自分で制御したい場合は truncate/roundup/ceil/floor といった +インスタンスメソッドを使用して下さい。 +</BLOCKQUOTE> +<LI><B>limit([n])</B></LI><BLOCKQUOTE> +生成されるBigDecimalオブジェクトの最大桁数をn桁に制限します。戻り値は +設定する前の値です。設定値のデフォルト値は0で、桁数無制限という意味です。 +nを指定しない場合は、現状の最大桁数が返ります。<BR> +mf = BigDecimal::limit(n)<BR> +</BLOCKQUOTE> +<LI><B>double_fig</B></LI><BLOCKQUOTE> +Ruby の Float クラスが保持できる有効数字の数を返します。 +<CODE><PRE> + p BigDecimal::double_fig # ==> 20 (depends on the CPU etc.) +</PRE></CODE> +double_figは以下の C プログラムの結果と同じです。 +<CODE><PRE> + double v = 1.0; + int double_fig = 0; + while(v + 1.0 > 1.0) { + ++double_fig; + v /= 10; + } +</PRE></CODE> +</BLOCKQUOTE> + +<LI><B>BASE</B></LI><BLOCKQUOTE> +内部で使用される基数の値です。整数が 32 ビットの処理系では10000です。<BR> +b = BigDecimal::BASE<BR> +</BLOCKQUOTE> + +<LI><B>E</B></LI><BLOCKQUOTE> +自然対数の底e(=2.718281828....)を計算します(正直にテイラー展開で)。<BR> +e = BigDecimal::E(n)<BR> +nは必要な有効桁数を整数で指定します。 +</BLOCKQUOTE> +<LI><B>PI</B></LI><BLOCKQUOTE> +円周率(=3.14159265358979....)を計算します(J.Machinの公式を用います)。<BR> +e = BigDecimal::PI(n)<BR> +n は必要な有効桁数を整数で指定します。 +</BLOCKQUOTE> +</UL> + +<H4><U>インスタンスメソッド</U></H4> +<UL> +<LI><B>+</B></LI><BLOCKQUOTE> 加算(c = a + b)<BR> c の精度については「<A HREF="#PREC">計算精度について</A>」を参照してください。 -<LI>-</LI><BR> +</BLOCKQUOTE> + +<LI><B>-</B></LI><BLOCKQUOTE> 減算(c = a - b)、または符号反転(c = -a)<BR> c の精度については「<A HREF="#PREC">計算精度について</A>」を参照してください。 -<LI>*</LI><BR> + +</BLOCKQUOTE> +<LI><B>*</B></LI><BLOCKQUOTE> 乗算(c = a * b)<BR> cの精度は(aの精度)+(bの精度)程度です。<br> 詳しくは「<A HREF="#PREC">計算精度について</A>」を参照してください。 -<LI>/</LI><BR> +</BLOCKQUOTE> +<LI><B>/</B></LI><BLOCKQUOTE> 除算(c = a / b)<BR> c の精度については「<A HREF="#PREC">計算精度について</A>」を参照してください。 -<LI>assign</LI><BR> -以下のように使用します。<BR> -c = a.assign(n,f)<BR> -f > 0 なら、a を c に、そのまま代入します。 -f < 0 なら、-a を c に代入します。 -f の絶対値(|f|)は1か2を指定してください。 -|f|=2 のときは、c の最大精度が a の実精度より小さいときには -丸められます。|f|=1 のときは切り捨てられます。 -n は c の有効桁数です(n 桁以上の精度を持つ c が生成されます)。 - -<LI>add</LI><BR> +</BLOCKQUOTE> + +<LI><B>add</B></LI><BLOCKQUOTE> 以下のように使用します。<BR> c = a.add(b,n)<BR> c = a + b を最大で n 桁まで計算します。 a + b の精度が n より大きいときは丸められます。 -<LI>sub</LI><BR> +</BLOCKQUOTE> +<LI><B>sub</B></LI><BLOCKQUOTE> 以下のように使用します。<BR> c = a.sub(b,n)<BR> c = a - b を最大で n 桁まで計算します。 a - b の精度が n より大きいときは丸められます。 -<LI>mult</LI><BR> +</BLOCKQUOTE> +<LI><B>mult</B></LI><BLOCKQUOTE> 以下のように使用します。<BR> c = a.mult(b,n)<BR> c = a * b を最大で n 桁まで計算します。 a * b の精度が n より大きいときは丸められます。 -<LI>div</LI><BR> +</BLOCKQUOTE> +<LI><B>div</B></LI><BLOCKQUOTE> 以下のように使用します。<BR> c,r = a.div(b,n)<BR> c=a/b の計算をします。 r には剰余が代入されます。a/bは @@ -220,63 +261,91 @@ c=a/b の計算をします。 r には剰余が代入されます。a/bは と異なり、c は整数とは限りません。 また、 c は丸められることはありません。 a = c*b + r の関係は成立します。 -<LI>%</LI><BR> +</BLOCKQUOTE> +<LI><B>%</B></LI><BLOCKQUOTE> r = a%b <BR> a/b の余りを計算します。以下の計算と同じものです。<BR> r = a-((a/b).floor)*b<BR> -<LI>fix</LI><BR> +</BLOCKQUOTE> +<LI><B>fix</B></LI><BLOCKQUOTE> a の小数点以下の切り捨て。<BR> c = a.fix -<LI>frac</LI><BR> +</BLOCKQUOTE> +<LI><B>frac</B></LI><BLOCKQUOTE> a の整数部分の切り捨て。<BR> c = a.frac -<LI>floor</LI><BR> -a 以下の最大整数を表す値(BigDecimal 値)を返します。<BR> +</BLOCKQUOTE> + +<LI><B>floor[(n)]</B></LI><BLOCKQUOTE> c = a.floor<BR> -以下のように引数を与えて、小数点以下 n+1 位の数字を操作することもできます -(少数点以下を、最大 n 桁にします)。<BR> -c = BigDecimal("1.23456")<BR> -d = c.floor(4) # d = 1.2345 になります。<BR> - n が負のときは小数点以上 n 桁目を操作します。<BR> -c = BigDecimal("15.23456")<BR> -d = c.floor(-1) # d = 10.0 になります。<BR> - -<LI>ceil</LI><BR> -a 以上の整数のうち、最も小さい整数を計算し、その値(BigDecimal 値)を返します。<BR> +a 以下の最大整数(BigDecimal 値)を返します。 +<PRE><CODE> +c = BigDecimal("1.23456").floor # ==> 1 +c = BigDecimal("-1.23456").floor # ==> -2 +</CODE></PRE> +以下のように引数 n を与えることもできます。<BR> +n>=0 なら、小数点以下 n+1 位の数字を操作します(少数点以下を、最大 n 桁にします)。<BR> +n が負のときは小数点以上 n 桁目を操作します(小数点位置から左に少なくとも n 個の 0 が並びます)。<BR> +<PRE><CODE> + c = BigDecimal::new("1.23456").floor(4) # ==> 1.2345 + c = BigDecimal::new("15.23456").floor(-1) # ==> 10.0 +</CODE></PRE> + +</BLOCKQUOTE> +<LI><B>ceil[(n)]</B></LI><BLOCKQUOTE> c = a.ceil<BR> -以下のように引数を与えて、小数点以下 n+1 位の数字を操作することもできます -(少数点以下を、最大 n 桁にします)。<BR> -c = BigDecimal::new("1.23456")<BR> -d = c.ceil(4) # d = 1.2346 になります。<BR> - n が負のときは小数点以上 n 桁目をを操作します。<BR> -c = BigDecimal::new("15.23456")<BR> -d = c.ceil(-1) # d = 20.0 になります。<BR> - -<LI>round</LI><BR> -小数点以下第一位の数を四捨五入して整数(BigDecimal 値)にします。<BR> +a 以上の整数のうち、最も小さい整数を計算し、その値(BigDecimal 値)を返します。 +<PRE><CODE> +c = BigDecimal("1.23456").ceil # ==> 2 +c = BigDecimal("-1.23456").ceil # ==> -1 +</CODE></PRE> + +以下のように引数を与えて、小数点以下 n+1 位の数字を操作することもできます。<BR> +n>=0 なら、小数点以下 n+1 位の数字を操作します(少数点以下を、最大 n 桁にします)。<BR> + n が負のときは小数点以上 n 桁目をを操作します(小数点位置から左に少なくとも n 個の 0 が並びます)。<BR> +<PRE><CODE> + c = BigDecimal::new("1.23456").ceil(4) # ==> 1.2346 + c = BigDecimal::new("15.23456").ceil(-1) # ==> 20.0 +</CODE></PRE> + +</BLOCKQUOTE> +<LI><B>round[(n[,b])]</B></LI><BLOCKQUOTE> c = a.round<BR> -以下のように引数を与えて、小数点以下 n+1 位の数字を操作することもできます -(少数点以下を、最大 n 桁にします)。<BR> -n が正の時は、小数点以下 n+1 位の数字を四捨五入します。 -c = BigDecimal::new("1.23456")<BR> -d = c.round(4) # d = 1.235 になります。<BR> - n が負のときは小数点以上 n 桁目をを操作します。<BR> -c = BigDecimal::new("15.23456")<BR> -d = c.round(-1) # d = 20.0 になります。<BR> - -<LI>truncate</LI><BR> -小数点以下の数を切り捨てて整数(BigDecimal 値)にします。<BR> +小数点以下第一位の数を四捨五入して整数(BigDecimal 値)にします。<BR> +<PRE><CODE> + c = BigDecimal("1.23456").round # ==> 1 + c = BigDecimal("-1.23456").round # ==> -1 +</CODE></PRE> + +以下のように引数を与えて、小数点以下 n+1 位の数字を操作することもできます。<BR> +n が正の時は、小数点以下 n+1 位の数字を四捨五入します(少数点以下を、最大 n 桁にします)。<BR> +n が負のときは小数点以上 n 桁目をを操作します(小数点位置から左に少なくとも n 個の 0 が並びます)。 +<PRE><CODE> +c = BigDecimal::new("1.23456").round(4) # ==> 1.2346 +c = BigDecimal::new("15.23456").round(-1) # ==> 20.0 +</CODE></PRE> +2番目の引数(デフォルトは 0)にゼロ以外を指定すると、いわゆる Banker's rounding になります。<BR> + Banker's rounding とは、四捨五入する数字を p として、p < 5 なら切り捨て p > 5 なら切り上げ、 +p がちょうど5のときだけは切り上げ先の数字+1が偶数になるときだけ切り上げます。 +<PRE><CODE> +c = BigDecimal::new("1.23456").round(3,1) # ==> 1.234 +c = BigDecimal::new("1.23356").round(3,1) # ==> 1.234 +</CODE></PRE> + +</BLOCKQUOTE> +<LI><B>truncate</B></LI><BLOCKQUOTE> c = a.truncate<BR> -以下のように引数を与えて、小数点以下 n+1 位の数字を操作することもできます -(少数点以下を、最大 n 桁にします)。<BR> -n が正の時は、小数点以下 n+1 位の数字を切り捨てます。 -c = BigDecimal::new("1.23456")<BR> -d = c.truncate(4) # d = 1.2345 になります。<BR> - n が負のときは小数点以上 n 桁目をを操作します。<BR> -c = BigDecimal::new("15.23456")<BR> -d = c.truncate(-1) # d = 10.0 になります。<BR> - -<LI>divmod</LI><BR> +小数点以下の数を切り捨てて整数(BigDecimal 値)にします。<BR> +以下のように引数を与えて、小数点以下 n+1 位の数字を操作することもできます。<BR> +n が正の時は、小数点以下 n+1 位の数字を切り捨てます(少数点以下を、最大 n 桁にします)。 +n が負のときは小数点以上 n 桁目をを操作します(小数点位置から左に少なくとも n 個の 0 が並びます)。<BR> +<PRE><CODE> +c = BigDecimal::new("1.23456").truncate(4) # ==> 1.2345 +c = BigDecimal::new("15.23456").truncate(-1) # ==> 10.0 +</CODE></PRE> + +</BLOCKQUOTE> +<LI><B>divmod</B></LI><BLOCKQUOTE> 商と剰余の配列を返します。<BR> c,r = a.divmod(b) # a = c*b + r<BR> divmodメソッドは a = c * b + r となる a / b の浮動小数点型の商 c と剰余 r を @@ -284,85 +353,44 @@ divmodメソッドは a = c * b + r となる a / b の浮動小数点型の商 c と剰余 r を c = (a/b).floor <BR> r = a - c*b<BR> で計算されます。 -<LI>remainder</LI><BR> +</BLOCKQUOTE> +<LI><B>remainder</B></LI><BLOCKQUOTE> r=a.remainder(b)<BR> a/b の剰余 r を計算します。<BR> c = (a/b).fix <BR> r = a - c*b<BR> で計算されます。 -<LI>abs</LI><BR> +</BLOCKQUOTE> +<LI><B>abs</B></LI><BLOCKQUOTE> aの絶対値<BR> c = a.abs<BR> -<LI>to_i</LI><BR> +</BLOCKQUOTE> +<LI><B>to_i</B></LI><BLOCKQUOTE> 少数点以下を切り捨てて整数に変換します。<BR> i = a.to_i<BR> i は値に応じて Fixnum か Bignum になります。 a が Infinity や NaN のとき、i は nil になります。 -<LI>to_f</LI><BR> +</BLOCKQUOTE> +<LI><B>to_f</B></LI><BLOCKQUOTE> dup と全く同じです。 同じ値の BigDecimal オブジェクトを生成します。 -<LI>to_s[(n)]</LI><BR> +</BLOCKQUOTE> +<LI><B>to_s[(n)]</B></LI><BLOCKQUOTE> 文字列に変換します("0.xxxxxEn"の形になります)。<BR> s = a.to_s<BR> n が指定されたときは、仮数部分を n 桁毎に空白で区切ります。<BR> s = a.to_s(n) -<LI>exponent</LI><BR> +</BLOCKQUOTE> +<LI><B>exponent</B></LI><BLOCKQUOTE> 指数部を整数値で返します。 n = a.exponent <BR> は a の値が 0.xxxxxxx*10**n を意味します。 -<LI>E</LI><BR> -自然対数の底e(=2.718281828....)を計算します(正直にテイラー展開で)。<BR> -e = BigDecimal::E(n)<BR> -nは必要な有効桁数を整数で指定します。 -<LI>PI</LI><BR> -円周率(=3.14159265358979....)を計算します(J.Machinの公式を用います)。<BR> -e = BigDecimal::PI(n)<BR> -n は必要な有効桁数を整数で指定します。 -<LI>BASE</LI><BR> -内部で使用される基数の値です。整数が 32 ビットの処理系では10000です。<BR> -b = BigDecimal::BASE<BR> -<LI>mode</LI><BR> -BigDecimalの実行結果を制御します。以下の使用方法が定義されています。<BR> -f = BigDecimal::mode(BigDecimal::EXCEPTION_NaN,flag)<BR> -f = BigDecimal::mode(BigDecimal::EXCEPTION_INFINITY,flag)<BR> -f = BigDecimal::mode(BigDecimal::EXCEPTION_UNDERFLOW,flag)<BR> -f = BigDecimal::mode(BigDecimal::EXCEPTION_OVERFLOW,flag)<BR> -f = BigDecimal::mode(BigDecimal::EXCEPTION_ZERODIVIDE,flag)<BR> -f = BigDecimal::mode(BigDecimal::EXCEPTION_ALL,flag)<BR> - -EXCEPTION_NaN は結果が NaN になったときの指定です。 -EXCEPTION_INFINITY は結果が無限大(±Infinity) -になったときの指定です。 -EXCEPTION_UNDERFLOW は指数部がアンダーフローするときの指定です。 -EXCEPTION_OVERFLOW は指数部がオーバーフローするときの指定です。 -EXCEPTION_ZERODIVIDE はゼロによる割り算を実行したときの指定です。 -EXCEPTION_ALL は、可能な全てに対して一括して設定するときに -使用します。 -flag が true のときは、指定した状態になったときに例外を発行 -するようになります。 -flag が false(デフォルト)なら、例外は発行されません。計算結果は -以下のようになります。<BR> -EXCEPTION_NaN のとき、非数(NaN)<BR> -EXCEPTION_INFINITY のとき、無限(+ or -Infinity)<BR> -EXCEPTION_UNDERFLOW のとき、ゼロ<BR> -EXCEPTION_OVERFLOW のとき、+Infinity か -Infinity<BR> -EXCEPTION_ZERODIVIDE のとき、+Infinity か -Infinity<BR> -EXCEPTION_INFINITY、EXCEPTION_OVERFLOW、EXCEPTION_ZERODIVIDE -は今のところ同じです。<BR> -戻り値は、設定後の値です。「値」の意味は、例えば -BigDecimal::EXCEPTION_NaNと「値」の & が ゼロ以外ならば -EXCEPTION_NaNが設定されているという意味です。 -flag が nil、または、true と false 以外なら現在の設定値が返ります。 +</BLOCKQUOTE> -<LI>limit([n])</LI><BR> -生成されるBigDecimalオブジェクトの最大桁数をn桁に制限します。戻り値は -設定する前の値です。設定値のデフォルト値は0で、桁数無制限という意味です。 -nを指定しない場合は、現状の最大桁数が返ります。<BR> -mf = BigDecimal::limit(n)<BR> -<LI>sign</LI><BR> +<LI><B>sign</B></LI><BLOCKQUOTE> 値の属性を返します。 n = a.sign <BR> としたとき n の値は a が以下のときを意味します。<BR> @@ -375,26 +403,40 @@ n = BigDecimal::SIGN_NEGATIVE_FINITE(-2) : a は負の値<BR> n = BigDecimal::SIGN_POSITIVE_INFINITE(3) : a は+Infinity<BR> n = BigDecimal::SIGN_NEGATIVE_INFINITE(-3) : a は-Infinity<BR> -<LI>nan?</LI><BR> +</BLOCKQUOTE> +<LI><B>nan?</B></LI><BLOCKQUOTE> a.nan? は a がNaNのとき真を返します。 -<LI>infinite?</LI><BR> -a.infinite? は a が+∞または-∞のとき真を返します。 -<LI>finite?</LI><BR> +</BLOCKQUOTE> +<LI><B>infinite?</B></LI><BLOCKQUOTE> +a.infinite? は a が+∞のとき 1 、-∞のときは -1、それ以外のときは nil を返します。 +</BLOCKQUOTE> +<LI><B>finite?</B></LI><BLOCKQUOTE> a.finite? は a が∞または NaN でないとき真を返します。 +</BLOCKQUOTE> -<LI>to_parts</LI><BR> +<LI><B>zero?</B></LI><BLOCKQUOTE> +a が 0 なら true になります。<BR> +c = a.zero? +</BLOCKQUOTE> +<LI><B>nonzero?</B></LI><BLOCKQUOTE> +a が 0 なら nil、0 以外なら a そのものが返ります。<BR> +c = a.nonzero? + +</BLOCKQUOTE> +<LI><B>split</B></LI><BLOCKQUOTE> BigDecimal 値を 0.xxxxxxx*10**n と表現したときに、符号(NaNのときは 0、それ以外は+1か-1になります)、 仮数部分の文字列("xxxxxxx")と、基数(10)、更に指数 n を配列で 返します。<BR> -a=BigDecimal::new("3.14159265",10)<BR> -f,x,y,z = a.to_parts<BR> +a=BigDecimal::new("3.14159265")<BR> +f,x,y,z = a.split<BR> とすると、f=+1、x="314159265"、y=10、z=1になります。<BR> 従って、<BR> s = "0."+x<BR> b = f*(s.to_f)*(y**z)<BR> で Float に変換することができます。 -<LI>inspect</LI><BR> +</BLOCKQUOTE> +<LI><B>inspect</B></LI><BLOCKQUOTE> デバッグ出力に使用されます。<BR> p a=BigDecimal::new("3.14",10)<BR> とすると、[0x112344:'0.314E1',4(12)]のように出力されます。 @@ -402,47 +444,54 @@ p a=BigDecimal::new("3.14",10)<BR> 次の4は現在の有効桁数(表示より若干大きいことがあります)、 最後はオブジェクトが取り得る最大桁数になります。 -<LI>dup</LI><BR> +</BLOCKQUOTE> +<LI><B>dup</B></LI><BLOCKQUOTE> 同じ値の BigDecimal オブジェクトを生成します。 -<LI>sqrt</LI><BR> +</BLOCKQUOTE> +<LI><B>sqrt</B></LI><BLOCKQUOTE> aの有効桁 n 桁の平方根(n の平方根ではありません)。 これまた、正直にニュートン法で計算します。<BR> c = a.sqrt(n)<BR> -<LI>sincos</LI><BR> +</BLOCKQUOTE> +<LI><B>sincos</B></LI><BLOCKQUOTE> a の有効桁 n 桁の sin と cos を同時に(テイラー展開で)計算して、 sin と cos の配列を返します。 n は必要な有効桁数です( n の sin や cos を計算するわけではありません)。 <BR> sin,cos = a.sincos(n)<BR> |a|<2*3.1415....でないと正しい答えを計算できないこともあります。 -<LI>exp</LI><BR> +</BLOCKQUOTE> +<LI><B>exp</B></LI><BLOCKQUOTE> 自然対数の底e(=2.718281828....)の a 乗を計算します。<BR> c = a.exp(n)<BR> n は必要な有効桁数です。 -<LI>power</LI><BR> +</BLOCKQUOTE> +<LI><B>**</B></LI><BLOCKQUOTE> a の n 乗を計算します。nは整数。<BR> +c = a ** n<BR> +結果として c の有効桁は a の n 倍以上になるので注意。 +</BLOCKQUOTE> +<LI><B>power</B></LI><BLOCKQUOTE> +** と同じで、a の n 乗を計算します。nは整数。<BR> c = a.power(n)<BR> 結果として c の有効桁は a の n 倍以上になるので注意。 -<LI>zero?</LI><BR> -a が 0 なら true になります。<BR> -c = a.zero?<BR> -<LI>nonzero?</LI><BR> -a が 0 なら false、0 以外なら a そのものが返ります。<BR> -c = a.nonzero?<BR> -<LI><=></LI><BR> +</BLOCKQUOTE> + +<LI><B><=></B></LI><BLOCKQUOTE> a==b なら 0、a > b なら 1、a < b なら -1 になります。<BR> -c = a <=> b <BR> +c = a <=> b +</BLOCKQUOTE> </UL> 後は、読んで字の如くです。<BR> <UL> -<LI>==</LI> -<LI>===</LI> +<LI><B>==</B></LI> +<LI><B>===</B></LI> 「==」と同じですが case 文で使用されます。 -<LI>!=</LI> -<LI><</LI> -<LI><=</LI> -<LI>></LI> -<LI>>=</LI> +<LI><B>!=</B></LI> +<LI><B><</B></LI> +<LI><B><=</B></LI> +<LI><B>></B></LI> +<LI><B>>=</B></LI> </UL> <H3>coerceについて</H3> BigDecimal オブジェクトが算術演算子の左にあるときは、BigDecimal オブジェクトが |