More pathes from Tadasi Saito.

As discussed in ruby-dev ML:
  E,PI, etc are disabled.
  BigDecimal op String disabled.
  to_f changed.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4091 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
shigek 2003-07-18 15:23:23 +00:00
Родитель b31bca1b45
Коммит b10272dc37
5 изменённых файлов: 264 добавлений и 175 удалений

Просмотреть файл

@ -7,10 +7,10 @@ depend
extconf.rb
bigdecimal_en.html
bigdecimal_ja.html
lib/jacobian.rb
lib/newton.rb
lib/ludcmp.rb
lib/bigdecimal-rational.rb
lib/bigdecimal/jacobian.rb
lib/bigdecimal/newton.rb
lib/bigdecimal/ludcmp.rb
lib/bigdecimal/util.rb
sample/linear.rb
sample/nlsolve.rb
sample/pi.rb

Просмотреть файл

@ -9,6 +9,7 @@
* of this BigDecimal distribution.
*
* NOTES:
* For the notes other than listed bellow,see ruby CVS log.
* 2003-04-17
* Bug in negative.exp(n) reported by Hitoshi Miyazaki fixed.
* 2003-03-28
@ -34,11 +35,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <float.h>
#include <math.h>
#include "ruby.h"
#include "math.h"
#include "version.h"
/* #define USE_MUTABLE_METHOD */
/* #define ENABLE_NUMERIC_STRING */
/* #define ENABLE_TRIAL_METHOD */
/* #define ENABLE_BANG_METHOD */
VALUE rb_cBigDecimal;
@ -96,7 +102,6 @@ do_coerce(VALUE *x, VALUE *y)
{
VALUE ary;
VALUE a[2];
a[0] = *x; a[1] = *y;
ary = rb_rescue(coerce_body, (VALUE)a, coerce_rescue, (VALUE)a);
if (TYPE(ary) != T_ARRAY || RARRAY(ary)->len != 2) {
@ -135,7 +140,6 @@ ToValue(Real *p)
static Real *
GetVpValue(VALUE v, int must)
{
double dv;
Real *pv;
VALUE bg;
char szD[128];
@ -153,40 +157,14 @@ GetVpValue(VALUE v, int must)
case T_FIXNUM:
sprintf(szD, "%d", FIX2INT(v));
return VpCreateRbObject(VpBaseFig() * 2 + 1, szD);
case T_FLOAT:
pv = VpCreateRbObject(VpDblFig()*2,"0");
dv = RFLOAT(v)->value;
/* From float */
if (isinf(dv)) {
VpException(VP_EXCEPTION_INFINITY,"Computation including infinity",0);
if(dv==VpGetDoublePosInf()) {
VpSetPosInf(pv);
} else {
VpSetNegInf(pv);
}
} else
if (isnan(dv)) {
VpException(VP_EXCEPTION_NaN,"Computation including NaN(Not a number)",0);
VpSetNaN(pv);
} else {
if (VpIsNegDoubleZero(dv)) {
VpSetNegZero(pv);
} else if(dv==0.0) {
VpSetPosZero(pv);
} else if(dv==1.0) {
VpSetOne(pv);
} else if(dv==-1.0) {
VpSetOne(pv);
pv->sign = -pv->sign;
} else {
VpDtoV(pv,dv);
}
}
return pv;
#ifdef ENABLE_NUMERIC_STRING
case T_STRING:
SafeStringValue(v);
return VpCreateRbObject(strlen(RSTRING(v)->ptr) + VpBaseFig() + 1,
RSTRING(v)->ptr);
#endif /* ENABLE_NUMERIC_STRING */
case T_BIGNUM:
bg = rb_big2str(v, 10);
return VpCreateRbObject(strlen(RSTRING(bg)->ptr) + VpBaseFig() + 1,
@ -448,16 +426,44 @@ BigDecimal_induced_from(VALUE self, VALUE x)
return p->obj;
}
static VALUE
BigDecimal_to_f(VALUE self)
{
ENTER(1);
Real *p;
double d, d2, da;
S_LONG e;
GUARD_OBJ(p,GetVpValue(self,1));
if(VpVtoD(&d, &e, p)!=1) return rb_float_new(d);
errno = 0;
d2 = pow(10.0,(double)e);
da = fabs(d);
if(errno == ERANGE || da > (DBL_MAX / d2) || da < (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_coerce(VALUE self, VALUE other)
{
ENTER(2);
VALUE obj;
Real *b;
GUARD_OBJ(b,GetVpValue(other,1));
obj = rb_ary_new();
obj = rb_ary_push(obj, b->obj);
obj = rb_ary_push(obj, self);
if(TYPE(other) == T_FLOAT) {
obj = rb_ary_new();
obj = rb_ary_push(obj,other);
obj = rb_ary_push(obj,BigDecimal_to_f(self));
} else {
GUARD_OBJ(b,GetVpValue(other,1));
obj = rb_ary_new();
obj = rb_ary_push(obj, b->obj);
obj = rb_ary_push(obj, self);
}
return obj;
}
@ -677,14 +683,14 @@ BigDecimal_div(VALUE self, VALUE r)
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 */
SAVE(c);SAVE(res);SAVE(div);
/* a/b = c + r/b */
/* c xxxxx
r 00000yyyyy ==> (y/b)*BASE >= HALF_BASE
*/
/* Round */
if(VpIsDef(c)) {
if(VpIsDef(c) && (!VpIsZero(c))) {
VpInternalRound(c,0,c->frac[c->Prec-1],(VpBaseVal()*res->frac[0])/div->frac[0]);
}
return ToValue(c);
@ -731,8 +737,8 @@ BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */
Real *div=NULL, *mod=NULL;
obj = BigDecimal_DoDivmod(self,r,&div,&mod);
SAVE(div);SAVE(mod);
if(obj!=(VALUE)0) return obj;
SAVE(div);SAVE(mod);
return ToValue(mod);
}
@ -866,19 +872,6 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
return ToValue(cv);
}
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)
{
@ -967,7 +960,6 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
ENTER(5);
Real *c, *a;
int iLoc;
int sw;
U_LONG mx;
VALUE vLoc;
@ -1081,9 +1073,7 @@ BigDecimal_split(VALUE self)
VpSzMantissa(vp,psz1);
s = 1;
if(psz1[0]=='-') {
int i=0;
s = -1;
while(psz1[i]=psz1[i+1]) i++ ;
s = -1; ++psz1;
}
if(psz1[0]=='N') s=0; /* NaN */
e = VpExponent10(vp);
@ -1150,6 +1140,25 @@ BigDecimal_power(VALUE self, VALUE p)
return ToValue(y);
}
static VALUE
BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
{
ENTER(5);
Real *pv;
S_LONG mf;
VALUE nFig;
VALUE iniValue;
if(rb_scan_args(argc,argv,"11",&iniValue,&nFig)==1) {
mf = 0;
} else {
mf = GetPositiveInt(nFig);
}
SafeStringValue(iniValue);
GUARD_OBJ(pv,VpCreateRbObject(mf, RSTRING(iniValue)->ptr));
return ToValue(pv);
}
static VALUE
BigDecimal_new(int argc, VALUE *argv, VALUE self)
{
@ -1182,6 +1191,14 @@ BigDecimal_limit(int argc, VALUE *argv, VALUE self)
return nCur;
}
static VALUE
BigDecimal_sign(VALUE self)
{ /* sign */
int s = GetVpValue(self,1)->sign;
return INT2FIX(s);
}
#ifdef ENABLE_TRIAL_METHOD
static VALUE
BigDecimal_e(VALUE self, VALUE nFig)
{
@ -1222,13 +1239,6 @@ BigDecimal_exp(VALUE self, VALUE nFig)
return ToValue(c);
}
static VALUE
BigDecimal_sign(VALUE self)
{ /* sign */
int s = GetVpValue(self,1)->sign;
return INT2FIX(s);
}
static VALUE
BigDecimal_sincos(VALUE self, VALUE nFig)
{
@ -1252,9 +1262,9 @@ BigDecimal_sincos(VALUE self, VALUE nFig)
rb_ary_push(obj, objCos);
return obj;
}
#endif /* ENABLE_TRIAL_METHOD */
#ifdef USE_MUTABLE_METHOD
#ifdef ENABLE_BANG_METHOD
/**** Following methods are all MUTABLE and not currently activated. ****/
static void
CheckAssign(VALUE x, VALUE y)
@ -1348,7 +1358,7 @@ BigDecimal_mult3(VALUE self, VALUE c, VALUE a, VALUE b)
f = VpMult(cv,av,bv);
return INT2NUM(f);
}
#endif /* USE_MUTABLE_METHOD */
#endif /* ENABLE_BANG_METHOD */
void
Init_bigdecimal(void)
@ -1359,13 +1369,14 @@ Init_bigdecimal(void)
/* Class and method registration */
rb_cBigDecimal = rb_define_class("BigDecimal",rb_cNumeric);
/* Global function */
rb_define_global_function("BigDecimal", BigDecimal_global_new, -1);
/* Class methods */
rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, 2);
rb_define_singleton_method(rb_cBigDecimal, "new", BigDecimal_new, -1);
rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1);
rb_define_singleton_method(rb_cBigDecimal, "E", BigDecimal_e, 1);
rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0);
rb_define_singleton_method(rb_cBigDecimal, "PI", BigDecimal_pi, 1);
rb_define_singleton_method(rb_cBigDecimal, "induced_from",BigDecimal_induced_from, 1);
rb_define_singleton_method(rb_cBigDecimal, "_load", BigDecimal_load, 1);
@ -1417,8 +1428,8 @@ Init_bigdecimal(void)
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, "dup", BigDecimal_dup, 0); */
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);
@ -1428,8 +1439,6 @@ Init_bigdecimal(void)
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);
rb_define_method(rb_cBigDecimal, "==", BigDecimal_eq, 1);
rb_define_method(rb_cBigDecimal, "===", BigDecimal_eq, 1);
@ -1451,20 +1460,27 @@ Init_bigdecimal(void)
rb_define_method(rb_cBigDecimal, "truncate", BigDecimal_truncate, -1);
rb_define_method(rb_cBigDecimal, "_dump", BigDecimal_dump, -1);
#ifdef USE_MUTABLE_METHOD
#ifdef ENABLE_TRIAL_METHOD
rb_define_singleton_method(rb_cBigDecimal, "E", BigDecimal_e, 1);
rb_define_singleton_method(rb_cBigDecimal, "PI", BigDecimal_pi, 1);
rb_define_method(rb_cBigDecimal, "exp", BigDecimal_exp, 1);
rb_define_method(rb_cBigDecimal, "sincos", BigDecimal_sincos, 1);
#endif /* ENABLE_TRIAL_METHOD */
#ifdef ENABLE_BANG_METHOD
rb_define_singleton_method(rb_cBigDecimal, "assign!", BigDecimal_assign, 3);
rb_define_singleton_method(rb_cBigDecimal, "add!", BigDecimal_add3, 3);
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);
#endif /* USE_MUTABLE_METHOD */
#endif /* ENABLE_BANG_METHOD */
}
/*
*
* ============================================================================
*
* vp_ routines begins here
* vp_ routines begin from here.
*
* ============================================================================
*
@ -2064,7 +2080,7 @@ VpAlloc(U_LONG mx, char *szVal)
VP_EXPORT int
VpAsgn(Real *c, Real *a, int isw)
{
U_LONG j, n;
U_LONG n;
if(VpIsNaN(a)) {
VpSetNaN(c);
return 0;
@ -2080,7 +2096,7 @@ VpAsgn(Real *c, Real *a, int isw)
VpSetSign(c,(isw*VpGetSign(a))); /* set sign */
n =(a->Prec < c->MaxPrec) ?(a->Prec) :(c->MaxPrec);
c->Prec = n;
for(j=0;j < n; ++j) c->frac[j] = a->frac[j];
memcpy(c->frac, a->frac, n * sizeof(U_LONG));
/* Needs round ? */
if(c->Prec < a->Prec) {
VpInternalRound(c,n,(n>0)?a->frac[n-1]:0,a->frac[n]);
@ -2093,7 +2109,6 @@ VpAsgn(Real *c, Real *a, int isw)
return c->Prec*BASE_FIG;
}
/*
* c = a + b when operation = 1 or 2
* = a - b when operation = -1 or -2.
@ -2602,7 +2617,7 @@ VpMult(Real *c, Real *a, Real *b)
VpSetSign(c,VpGetSign(a)*VpGetSign(b)); /* set sign */
Carry = 0;
nc = ind_c = MxIndAB;
for(i = 0; i <= nc; i++) c->frac[i] = 0; /* Initialize c */
memset(c->frac, 0, (nc + 1) * sizeof(U_LONG)); /* Initialize c */
c->Prec = nc + 1; /* set precision */
for(nc = 0; nc < MxIndAB; ++nc, --ind_c) {
if(nc < MxIndB) { /* The left triangle of the Fig. */
@ -3113,7 +3128,7 @@ static void
VpFormatSt(char *psz,S_INT fFmt)
{
U_LONG ie;
U_LONG i, j;
U_LONG i;
S_INT nf = 0;
char ch;
int fDot = 0;
@ -3131,8 +3146,7 @@ VpFormatSt(char *psz,S_INT fFmt)
if(ch == 'E') break;
nf++;
if(nf > fFmt) {
for(j = ie; j >= i; --j)
psz[j + 1] = psz[j];
memmove(psz + i + 1, psz + i, ie - i + 1);
++ie;
nf = 0;
psz[i] = ' ';
@ -3283,7 +3297,7 @@ VpCtoV(Real *a, char *int_chr, U_LONG ni, char *frac, U_LONG nf, char *exp_chr,
mi = ni;
me = ne;
signe = 1;
for(i=0;i < ma;++i) a->frac[i] = 0;
memset(a->frac, 0, ma * sizeof(U_LONG));
if(ne > 0) {
i = 0;
if(exp_chr[0] == '-') {
@ -3398,24 +3412,51 @@ Final:
* DBLE_FIG ... Number of digits in a double variable.
*
* m -> d*10**e, 0<d<BASE
* [Returns]
* 0 ... Zero
* 1 ... Normal
* 2 ... Infinity
* -1 ... NaN
*/
VP_EXPORT void
VP_EXPORT int
VpVtoD(double *d, S_LONG *e, Real *m)
{
U_LONG ind_m, mm, fig;
double div;
int f = 1;
fig =(DBLE_FIG + BASE_FIG - 1) / BASE_FIG;
if(VpIsNaN(m)) {
*d = VpGetDoubleNaN();
*e = 0;
f = -1; /* NaN */
goto Exit;
} else
if(VpIsPosZero(m)) {
*d = 0.0;
*e = 0;
f = 0;
goto Exit;
} else
if(VpIsNegZero(m)) {
*d = VpGetDoubleNegZero();
*e = 0;
f = 0;
goto Exit;
} else
if(VpIsPosInf(m)) {
*d = VpGetDoublePosInf();
*e = 0;
f = 2;
goto Exit;
} else
if(VpIsNegInf(m)) {
*d = VpGetDoubleNegInf();
*e = 0;
f = 2;
goto Exit;
}
/* Normal number */
fig =(DBLE_FIG + BASE_FIG - 1) / BASE_FIG;
ind_m = 0;
mm = Min(fig,(m->Prec));
*d = 0.0;
@ -3435,7 +3476,7 @@ Exit:
printf(" DBLE_FIG = %ld\n", DBLE_FIG);
}
#endif /*_DEBUG */
return;
return f;
}
/*
@ -3479,7 +3520,7 @@ VpDtoV(Real *m, double d)
/* Now val = 0.xxxxx*BASE**ne */
mm = m->MaxPrec;
for(ind_m = 0;ind_m < mm;ind_m++) m->frac[ind_m] = 0;
memset(m->frac, 0, mm * sizeof(U_LONG));
for(ind_m = 0;val > 0.0 && ind_m < mm;ind_m++) {
val *=(double)((S_INT)BASE);
i =(U_LONG) val;
@ -3684,7 +3725,7 @@ Exit:
VP_EXPORT void
VpActiveRound(Real *y, Real *x, int f, int nf)
{
int n,i,j,ix,ioffset;
int n,i,ix,ioffset;
U_LONG v;
U_LONG div;
@ -3700,7 +3741,7 @@ VpActiveRound(Real *y, Real *x, int f, int nf)
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;
memset(y->frac+ix+1, 0, (y->Prec - (ix+1)) * sizeof(U_LONG));
/* VpNmlz(y); */
v = y->frac[ix];
/* drop digits after pointed digit */
@ -3929,6 +3970,7 @@ Exit:
return 1;
}
#ifdef ENABLE_TRIAL_METHOD
/*
* Calculates pi(=3.141592653589793238462........).
*/
@ -4216,6 +4258,7 @@ Exit:
VpFree(r);
VpFree(z);
}
#endif /* ENABLE_TRIAL_METHOD */
#ifdef _DEBUG
int

Просмотреть файл

@ -131,7 +131,7 @@ VP_EXPORT S_LONG VpExponent10(Real *a);
VP_EXPORT void VpSzMantissa(Real *a,char *psz);
VP_EXPORT void VpToString(Real *a,char *psz,int fFmt);
VP_EXPORT int VpCtoV(Real *a,char *int_chr,U_LONG ni,char *frac,U_LONG nf,char *exp_chr,U_LONG ne);
VP_EXPORT void VpVtoD(double *d,S_LONG *e,Real *m);
VP_EXPORT int 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);

Просмотреть файл

@ -81,21 +81,29 @@ to create BigDecimal objects,the program would like:<BR>
<CODE><PRE>
require 'bigdecimal'
a=BigDecimal::new("0.123456789123456789")
b=BigDecimal::new("123456.78912345678",40)
b=BigDecimal("123456.78912345678",40)
c=a+b
</PRE></CODE>
<H3>List of methods</H3>
In the following explanations,n specifies the minimum number of resulting significant digits,
not exactly but slightly excess memories will be allocated to newly created object.
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.
<P>
Some more methods are available in Ruby code (not C code).
To use them,just require util.rb as:
<PRE><CODE>
require "bigdecimal/util.rb"
</CODE></PRE>
String to BigDecimal conversion, BigDecimal to String conversion
(in "nnnnnn.mmmm" form not in "0.xxxxxEn" form) etc are defined.
For details,see the util.rb code.
<H4><U>Class methods</U></H4>
<UL>
<LI><B>new</B></LI><BLOCKQUOTE>
"new" method creates a new BigDecimal object.<BR>
a=BigDecimal::new(s[,n])<BR>
a=BigDecimal::new(s[,n]) or<BR>
a=BigDecimal(s[,n]) or<BR>
where:<BR>
s: Initial value string.<BR>
n: Maximum number of significant digits of a. n must be a Fixnum object.
@ -187,18 +195,6 @@ 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>
<H4><U>Instance methods</U></H4>
@ -394,14 +390,15 @@ means a = 0.xxxxxxx*10**n.
</BLOCKQUOTE>
<LI><B>to_f</B></LI><BLOCKQUOTE>
same as dup method.
creates a new BigDecimal object having same value.
Creates a new Float object having (nearly) the same value.
Use split method if you want to convert by yourself.
</BLOCKQUOTE>
</BLOCKQUOTE>
<LI><B>sign</B></LI><BLOCKQUOTE>
returns the 'attribute' of a.
n = a.sign <BR>
returns positive value if a &gt; 0,negative value if a &lt; 0,
otherwise zero if a == 0.<BR>
where the value of n means that a is:<BR>
n = BigDecimal::SIGN_NaN(0) : a is NaN<BR>
n = BigDecimal::SIGN_POSITIVE_ZERO(1) : a is +0<BR>
@ -455,28 +452,13 @@ where "0x112344" is the address,
'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.
</BLOCKQUOTE>
<LI><B>dup</B></LI><BLOCKQUOTE>
creates a new BigDecimal object having same value.
</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>
</BLOCKQUOTE>
</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.....
</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>
</BLOCKQUOTE>
<LI><B>**</B></LI><BLOCKQUOTE>
c = a ** n<BR>
returns the value of a powered by n.
@ -507,6 +489,41 @@ same as ==,used in case statement.
<LI>&gt;</LI>
<LI>&gt;=</LI>
</UL>
<H4><U>Class methods(trial version)</U></H4>
Following class methods are in trial stage, and not usable in default.
Uncomment /* #define ENABLE_TRIAL_METHOD */ in bigdecimal.c, compile and install
again if you want to use.
<UL>
<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>
<H4><U>Instance methods(trial version)</U></H4>
Following instance methods are in trial stage, and not usable in default.
Uncomment /* #define ENABLE_TRIAL_METHOD */ in bigdecimal.c, compile and install
again if you want to use.
<UL>
<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.....
</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>
</BLOCKQUOTE>
</UL>
<HR>
<H3>About 'coerce'</H3>
@ -521,7 +538,9 @@ same as ==,used in case statement.
BigDecimal object and the operation is performed,otherwise an error occures.</DD>
</DL>
Attention must be paid when a String is to be translated to BigDecimal.
String is not translated to BigDecimal in default.
Uncomment /* #define ENABLE_NUMERIC_STRING */ in bigdecimal.c, compile and install
again if you want to enable string to BigDecimal conversion.
Translation stops without error at the character representing non digit.
For instance,"10XX" is translated to 10,"XXXX" is translated to 0.<BR>
String representing zero or infinity such as "Infinity","+Infinity","-Infinity",and "NaN" can also be translated to BigDecimal unless false is specified by mode method.<BR>

Просмотреть файл

@ -84,7 +84,7 @@ bigdecimal.c,bigdecimal.h
<PRE>
require 'bigdecimal'
a=BigDecimal::new("0.123456789123456789")
b=BigDecimal::new("123456.78912345678",40)
b=BigDecimal("123456.78912345678",40)
c=a+b
</PRE>
</CODE>
@ -92,18 +92,27 @@ c=a+b
というような感じで使用します。
<H3>メソッド一覧</H3>
以下のようなメソッドが利用可能です。<BR>
記述上、BigDecimal オブジェクトを a,b,c,rで、String文字列オブジェクトを
s、整数を n で表記します。また、「有効桁数」とは BigDecimal が精度を保証する
桁数です。ぴったりではありません、若干の余裕を持って計算されます。また、
以下のメソッドが利用可能です。
「有効桁数」とは BigDecimal が精度を保証する桁数です。
ぴったりではありません、若干の余裕を持って計算されます。また、
例えば32ビットのシステムでは10進で4桁毎に計算します。従って、現状では、
内部の「有効桁数」は4の倍数となっています。
<P>
以下のメソッド以外にも、(C ではない) Ruby ソースの形で
提供されているものもあります。例えば、文字列から BigDecimal への
変換や、"0.xxxxxEn" という形式ではなく "nnnnn.mmmm" の形式の文字列
へ変換するメソッド等があります。利用するには
<PRE><CODE>
require "bigdecimal/util.rb"
</CODE></PRE>
のようにします。詳細は util.rb の内容を参照して下さい。
<H4><U>クラスメソッド</U></H4>
<UL>
<LI><B>new</B></LI><BLOCKQUOTE>
新しい BigDecimal オブジェクトを生成します。<BR>
a=BigDecimal::new(s[,n])<BR>
a=BigDecimal::new(s[,n]) または<BR>
a=BigDecimal(s[,n])<BR>
s は初期値を文字列で指定します.
n は必要な有効桁数a の最大有効桁数)を整数で指定します。
n が 0 または省略されたときは、n の値は s の有効桁数とみなされます。
@ -195,17 +204,6 @@ double_fig
内部で使用される基数の値です。整数が 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....)を計算しますJMachinの公式を用います<BR>
e = BigDecimal::PI(n)<BR>
n は必要な有効桁数を整数で指定します。
</BLOCKQUOTE>
</UL>
<H4><U>インスタンスメソッド</U></H4>
@ -374,8 +372,9 @@ i
a が Infinity や NaN のとき、i は nil になります。
</BLOCKQUOTE>
<LI><B>to_f</B></LI><BLOCKQUOTE>
dup と全く同じです。
同じ値の BigDecimal オブジェクトを生成します。
Float オブジェクトに変換します。
よりきめ細かい値が必要ならば split メソッドを利用して
ください。
</BLOCKQUOTE>
<LI><B>to_s[(n)]</B></LI><BLOCKQUOTE>
文字列に変換します("0.xxxxxEn"の形になります)。<BR>
@ -391,7 +390,7 @@ n = a.exponent <BR>
</BLOCKQUOTE>
<LI><B>sign</B></LI><BLOCKQUOTE>
の属性を返します。
が正(sign &gt; 0)、負(sign &lt; 0)、その他(sigh==0)であるかの情報を返します。
n = a.sign <BR>
としたとき n の値は a が以下のときを意味します。<BR>
() の中の数字は、実際の値です(<A HREF="#STRUCT">「内部構造」</A>を参照)。<BR>
@ -443,28 +442,6 @@ p a=BigDecimal::new("3.14",10)<BR>
最初の16進数はオブジェクトのアドレス、次の '0.314E1' は値、
次の4は現在の有効桁数(表示より若干大きいことがあります)、
最後はオブジェクトが取り得る最大桁数になります。
</BLOCKQUOTE>
<LI><B>dup</B></LI><BLOCKQUOTE>
同じ値の BigDecimal オブジェクトを生成します。
</BLOCKQUOTE>
<LI><B>sqrt</B></LI><BLOCKQUOTE>
aの有効桁 n 桁の平方根n の平方根ではありません)。
これまた、正直にニュートン法で計算します。<BR>
c = a.sqrt(n)<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....でないと正しい答えを計算できないこともあります
</BLOCKQUOTE>
<LI><B>exp</B></LI><BLOCKQUOTE>
自然対数の底e(=2.718281828....)の a 乗を計算します。<BR>
c = a.exp(n)<BR>
n は必要な有効桁数です。
</BLOCKQUOTE>
<LI><B>**</B></LI><BLOCKQUOTE>
a の n 乗を計算します。nは整数。<BR>
@ -476,6 +453,11 @@ c = a ** n<BR>
c = a.power(n)<BR>
結果として c の有効桁は a の n 倍以上になるので注意。
</BLOCKQUOTE>
<LI><B>sqrt</B></LI><BLOCKQUOTE>
aの有効桁 n 桁の平方根n の平方根ではありません)を
ニュートン法で計算します。<BR>
c = a.sqrt(n)<BR>
</BLOCKQUOTE>
<LI><B>&lt=&gt</B></LI><BLOCKQUOTE>
a==b なら 0、a &gt b なら 1、a &lt b なら -1 になります。<BR>
@ -493,11 +475,56 @@ c = a &lt=&gt b
<LI><B>&gt</B></LI>
<LI><B>&gt=</B></LI>
</UL>
<H4><U>(評価段階の)クラスメソッド</U></H4>
以下のクラスメソッドは、まだ評価段階ですので、通常では
使用できません。使用するには bigdecimal.c の
「/* #define ENABLE_TRIAL_METHOD */」
のコメントを外し、再コンパイル・再インストールが必要です。
<UL>
<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....)を計算しますJMachinの公式を用います<BR>
e = BigDecimal::PI(n)<BR>
n は必要な有効桁数を整数で指定します。
</BLOCKQUOTE>
</UL>
<H4><U>(評価段階の)インスタンスメソッド</U></H4>
以下のインスタンスメソッドは、まだ評価段階ですので、通常では
使用できません。使用するには bigdecimal.c の
「/* #define ENABLE_TRIAL_METHOD */」
のコメントを外して、再コンパイル・再インストールが必要です。
<UL>
<LI><B>sincos</B></LI><BLOCKQUOTE>
a の有効桁 n 桁の sin と cos を同時に(テイラー展開で)計算して、
sin と cos の配列を返します。
n は必要な有効桁数です( n の sin や cos を計算するわけではありません)。
<BR>
sin,cos = a.sincos(n)<BR>
|a| &lt; 2*3.1415....でないと正しい答えを計算できないこともあります。
</BLOCKQUOTE>
<LI><B>exp</B></LI><BLOCKQUOTE>
自然対数の底e(=2.718281828....)の a 乗を計算します。<BR>
c = a.exp(n)<BR>
n は必要な有効桁数です。
</BLOCKQUOTE>
</UL>
<H3>coerceについて</H3>
BigDecimal オブジェクトが算術演算子の左にあるときは、BigDecimal オブジェクトが
右にあるオブジェクトを(必要なら) BigDecimal に変換してから計算します。
従って、BigDecimal オブジェクト以外でも数値を意味するものなら右に置けば
演算は可能です。<BR><BR>
演算は可能です。<BR>
ただし、文字列は(通常)数値に自動変換することはできません。
文字列を数値に自動変換に自動変換したい場合は bigfloat.c の
「/* #define ENABLE_NUMERIC_STRING */」のコメントを外してから、
再コンパイル、再インストールする必要があります。
文字列で数値を与える場合は注意が必要です。数値に変換できない文字があると、
単に変換を止めるだけでエラーにはなりません。"10XX"なら10、"XXXX"は0
と扱われます。<BR>