diff options
author | shigek <shigek@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-07-28 02:56:43 +0000 |
---|---|---|
committer | shigek <shigek@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-07-28 02:56:43 +0000 |
commit | 4cbf09d1fe858f39bd091a6cbe59dcc56ce463aa (patch) | |
tree | 3e58bf6e621cda921eea09a01a71c40e628017ae | |
parent | b388591ab76c81eb2c7b4a5d66a840235f1365df (diff) |
Bug fix from Javier Goizueta.
ROUND_MODE & round changed(source & docs).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4187 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ext/bigdecimal/bigdecimal.c | 46 | ||||
-rw-r--r-- | ext/bigdecimal/bigdecimal.h | 4 | ||||
-rw-r--r-- | ext/bigdecimal/bigdecimal_en.html | 48 | ||||
-rw-r--r-- | ext/bigdecimal/bigdecimal_ja.html | 59 |
4 files changed, 86 insertions, 71 deletions
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c index a5d29660fb..a1253e92e7 100644 --- a/ext/bigdecimal/bigdecimal.c +++ b/ext/bigdecimal/bigdecimal.c @@ -919,12 +919,15 @@ static VALUE BigDecimal_round(int argc, VALUE *argv, VALUE self) { ENTER(5); - Real *c, *a; - int iLoc; - int sw; + Real *c, *a; + int iLoc; U_LONG mx; - VALUE vLoc; - int na = rb_scan_args(argc,argv,"01",&vLoc); + VALUE vLoc; + VALUE vRound; + + int sw = VpGetRoundMode(); + + int na = rb_scan_args(argc,argv,"02",&vLoc,&vRound); switch(na) { case 0: iLoc = 0; @@ -933,12 +936,18 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self) Check_Type(vLoc, T_FIXNUM); iLoc = FIX2INT(vLoc); break; + case 2: + Check_Type(vLoc, T_FIXNUM); + iLoc = FIX2INT(vLoc); + Check_Type(vRound, T_FIXNUM); + sw = VpSetRoundMode(FIX2INT(vRound)); + break; } GUARD_OBJ(a,GetVpValue(self,1)); mx = a->Prec *(VpBaseFig() + 1); GUARD_OBJ(c,VpCreateRbObject(mx, "0")); - VpActiveRound(c,a,VpGetRoundMode(),iLoc); + VpActiveRound(c,a,sw,iLoc); return ToValue(c); } @@ -1291,7 +1300,7 @@ Init_bigdecimal(void) rb_define_const(rb_cBigDecimal, "ROUND_HALF_DOWN",INT2FIX(VP_ROUND_HALF_DOWN)); rb_define_const(rb_cBigDecimal, "ROUND_CEILING",INT2FIX(VP_ROUND_CEIL)); rb_define_const(rb_cBigDecimal, "ROUND_FLOOR",INT2FIX(VP_ROUND_FLOOR)); - rb_define_const(rb_cBigDecimal, "ROUND_EVEN",INT2FIX(VP_ROUND_EVEN)); + rb_define_const(rb_cBigDecimal, "ROUND_HALF_EVEN",INT2FIX(VP_ROUND_HALF_EVEN)); /* Constants for sign value */ rb_define_const(rb_cBigDecimal, "SIGN_NaN",INT2FIX(VP_SIGN_NaN)); @@ -1484,13 +1493,12 @@ VpGetRoundMode(void) VP_EXPORT unsigned long VpSetRoundMode(unsigned long n) { - unsigned long s = gfRoundMode; - if(n!=VP_ROUND_UP && n!=VP_ROUND_DOWN && - n!=VP_ROUND_HALF_UP && n!=VP_ROUND_HALF_DOWN && - n!=VP_ROUND_CEIL && n!=VP_ROUND_FLOOR && - n!=VP_ROUND_EVEN) return s; - gfRoundMode = n; - return s; + if(n==VP_ROUND_UP || n!=VP_ROUND_DOWN || + n==VP_ROUND_HALF_UP || n!=VP_ROUND_HALF_DOWN || + n==VP_ROUND_CEIL || n!=VP_ROUND_FLOOR || + n==VP_ROUND_HALF_EVEN + ) gfRoundMode = n; + return gfRoundMode; } /* @@ -3212,7 +3220,7 @@ VpCtoV(Real *a, char *int_chr, U_LONG ni, char *frac, U_LONG nf, char *exp_chr, ++me; } while(i < me) { - es = e*BASE_FIG; + es = e*((S_INT)BASE_FIG); e = e * 10 + exp_chr[i] - '0'; if(es>e*((S_INT)BASE_FIG)) { return VpException(VP_EXCEPTION_INFINITY,"Exponent overflow",0); @@ -3247,8 +3255,8 @@ VpCtoV(Real *a, char *int_chr, U_LONG ni, char *frac, U_LONG nf, char *exp_chr, while(ef) { if(e>=0) eb = e; else eb = -e; - ef = eb / BASE_FIG; - ef = eb - ef * BASE_FIG; + ef = eb / ((S_INT)BASE_FIG); + ef = eb - ef * ((S_INT)BASE_FIG); if(ef) { ++j; /* Means to add one more preceeding zero */ ++e; @@ -3669,7 +3677,7 @@ VpMidRound(Real *y, int f, int nf) case VP_ROUND_FLOOR: /* floor */ if(v && (VpGetSign(y)<0)) ++div; break; - case VP_ROUND_EVEN: /* Banker's rounding */ + case VP_ROUND_HALF_EVEN: /* Banker's rounding */ if(v>5) ++div; else if(v==5) { if(i==(BASE_FIG-1)) { @@ -3751,7 +3759,7 @@ VpInternalRound(Real *c,int ixDigit,U_LONG vPrev,U_LONG v) case VP_ROUND_FLOOR: /* floor */ if(v && (VpGetSign(c)<0)) f = 1; break; - case VP_ROUND_EVEN: /* Banker's rounding */ + case VP_ROUND_HALF_EVEN: /* Banker's rounding */ if(v>5) f = 1; else if(v==5 && vPrev%2) f = 1; break; diff --git a/ext/bigdecimal/bigdecimal.h b/ext/bigdecimal/bigdecimal.h index 62c89dce50..d8fa35d3c5 100644 --- a/ext/bigdecimal/bigdecimal.h +++ b/ext/bigdecimal/bigdecimal.h @@ -59,7 +59,7 @@ extern "C" { #define VP_ROUND_HALF_DOWN 4 #define VP_ROUND_CEIL 5 #define VP_ROUND_FLOOR 6 -#define VP_ROUND_EVEN 7 +#define VP_ROUND_HALF_EVEN 7 #define VP_SIGN_NaN 0 /* NaN */ #define VP_SIGN_POSITIVE_ZERO 1 /* Positive zero */ @@ -121,7 +121,7 @@ VP_EXPORT double VpGetDoubleNegZero(void); VP_EXPORT U_LONG VpGetPrecLimit(void); VP_EXPORT U_LONG VpSetPrecLimit(U_LONG n); -/* Computation mode */ +/* Round mode */ VP_EXPORT unsigned long VpGetRoundMode(void); VP_EXPORT unsigned long VpSetRoundMode(unsigned long n); diff --git a/ext/bigdecimal/bigdecimal_en.html b/ext/bigdecimal/bigdecimal_en.html index ed192fca58..2d86adcc6b 100644 --- a/ext/bigdecimal/bigdecimal_en.html +++ b/ext/bigdecimal/bigdecimal_en.html @@ -156,18 +156,22 @@ Suppose the return value of the mode method is f,then <B>[ROUND error control]</B><P> Rounding operation can be controlled as: <BLOCKQUOTE> -f = BigDecimal::mode(BigDecimal::COMP_MODE,flag) +f = BigDecimal::mode(BigDecimal::ROUND_MODE,flag) </BLOCKQUOTE> where flag must be one of: <TABLE> -<TR><TD>COMP_MODE_TRUNCATE</TD><TD>truncate</TD></TR> -<TR><TD>COMP_MODE_ROUND</TD><TD>round,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> + +<TR><TD>ROUND_UP</TD><TD>round away from zero.</TD></TR> +<TR><TD>ROUND_DOWN</TD><TD>round towards zero(truncate).</TD></TR> +<TR><TD>ROUND_HALF_UP</TD><TD>round up if the digit >= 5 otherwise truncated(default).</TD></TR> +<TR><TD>ROUND_HALF_DOWN</TD><TD>round up if the digit >= 6 otherwise truncated.</TD></TR> +<TR><TD>ROUND_HALF_EVEN</TD><TD>round towards the even neighbor(Banker's rounding). +<TR><TD>ROUND_CEILING</TD><TD>round towards positive infinity(ceil).</TD></TR> +<TR><TD>ROUND_FLOOR</TD><TD>round towards negative infinity(floor).</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, +New rounding mode is returned,nil is returned if any argument is not an integer. +Bad specification is ignored.<BR> +The digit location for rounding operation can not be specified by this mode method, use truncate/round/ceil/floor/add/sub/mult/div mthods for each instance instead. </BLOCKQUOTE> @@ -286,8 +290,8 @@ 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). <CODE><PRE> - c = BigDecimal::new("1.23456").floor(4) # ==> 1.2345 - c = BigDecimal::new("15.23456").floor(-1) # ==> 10.0 + c = BigDecimal("1.23456").floor(4) # ==> 1.2345 + c = BigDecimal("15.23456").floor(-1) # ==> 10.0 </PRE></CODE> </BLOCKQUOTE> @@ -304,37 +308,33 @@ 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). <CODE><PRE> - c = BigDecimal::new("1.23456").ceil(4) # ==> 1.2346 - c = BigDecimal::new("15.23456").ceil(-1) # ==> 20.0 + c = BigDecimal("1.23456").ceil(4) # ==> 1.2346 + c = BigDecimal("15.23456").ceil(-1) # ==> 20.0 </PRE></CODE> </BLOCKQUOTE> <LI><B>round[(n[,b])]</B></LI><BLOCKQUOTE> c = a.round<BR> -round a to the nearest 1�D<BR> +round a to the nearest 1(default)�D<BR> <CODE><PRE> c = BigDecimal("1.23456").round # ==> 1 c = BigDecimal("-1.23456").round # ==> -1 </PRE></CODE> +The rounding operation changes according to BigDecimal::mode(BigDecimal::ROUND_MODE,flag) if specified. 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+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). <CODE><PRE> c = BigDecimal::new("1.23456").round(4) # ==> 1.2346 c = BigDecimal::new("15.23456").round(-1) # ==> 20.0 </PRE></CODE> -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. +Rounding operation can be specified by setting the second optional argument b with the valid ROUND_MODE.<BR> <CODE><PRE> -c = BigDecimal::new("1.23456").round(3,1) # ==> 1.234 -c = BigDecimal::new("1.23356").round(3,1) # ==> 1.234 +c = BigDecimal::new("1.23456").round(3,BigDecimal::ROUND_HALF_EVEN) # ==> 1.234 +c = BigDecimal::new("1.23356").round(3,BigDecimal::ROUND_HALF_EVEN) # ==> 1.234 </PRE></CODE> </BLOCKQUOTE> @@ -728,11 +728,11 @@ As +,-,and * are always exact(no round operation is performed unless BigDecimal. which means more momories are required to keep computation results. But,the division such as c=1.0/3.0 will always be rounded.<BR> -<H3>2. assign,add,sub,mult,div</H3> +<H3>2. add,sub,mult,div</H3> The length of the significant digits obtained from +,-,*,/ is always defined by that of right and left side of the operator. To specify the length of the significant digits by your self, -use methos assign,add,sub,mult,div. +use methos add,sub,mult,div. <CODE><PRE> BigDecimal("2").div(3,12) # 2.0/3.0 => 0.6666666666 67E0 </PRE></CODE> diff --git a/ext/bigdecimal/bigdecimal_ja.html b/ext/bigdecimal/bigdecimal_ja.html index f78d63a9b6..31e852bd02 100644 --- a/ext/bigdecimal/bigdecimal_ja.html +++ b/ext/bigdecimal/bigdecimal_ja.html @@ -166,22 +166,26 @@ EXCEPTION_NaN���ݒ肳��Ă���Ƃ����Ӗ��ł��B<BR> <B>[�ۂߏ����w��]</B><P> �v�Z�r���̊ۂߑ���̎w�肪�ł��܂��B <BLOCKQUOTE> -f = BigDecimal::mode(BigDecimal::COMP_MODE,flag) +f = BigDecimal::mode(BigDecimal::ROUND_MODE,flag) </BLOCKQUOTE> �̌`���Ŏw�肵�܂��B<BR> �����ŁAflag �͈ȉ�(���ʓ��͑Ή�����C���X�^���X���\�b�h)�̈���w�肵�܂��B <TABLE> -<TR><TD>COMP_MODE_TRUNCATE</TD><TD>�S�Đ�̂Ă܂�(truncate)�B</TD></TR> -<TR><TD>COMP_MODE_ROUND</TD><TD>�l�̌ܓ����܂�(round�A�f�t�H���g)�B</TD></TR> -<TR><TD>COMP_MODE_CEIL</TD><TD>���l�̑傫�����ɌJ��グ�܂�(ceil)�B</TD></TR> -<TR><TD>COMP_MODE_FLOOR</TD><TD>���l�̏��������ɌJ�艺���܂�(floor)�B</TD></TR> -<TR><TD>COMP_MODE_EVEN</TD><TD>�l�̘Z�����܂��B�T�̎��͏�ʂP������̎��̂J��グ�܂�(Banker's rounding)�B</TD></TR> +<TR><TD>ROUND_UP</TD><TD>�S�Đ�グ�܂��B</TD></TR> +<TR><TD>ROUND_DOWN</TD><TD>�S�Đ�̂Ă܂�(truncate)�B</TD></TR> +<TR><TD>ROUND_HALF_UP</TD><TD>�l�̌ܓ����܂�(�f�t�H���g)�B</TD></TR> +<TR><TD>ROUND_HALF_DOWN</TD><TD>�̘Z�����܂��B</TD></TR> +<TR><TD>ROUND_HALF_EVEN</TD><TD>�l�̘Z�����܂��B�T�̎��͏�ʂP������̎��̂J��グ�܂�(Banker's rounding)�B</TD></TR> +<TR><TD>ROUND_CEILING</TD><TD>���l�̑傫�����ɌJ��グ�܂�(ceil)�B</TD></TR> +<TR><TD>ROUND_FLOOR</TD><TD>���l�̏��������ɌJ�艺���܂�(floor)�B</TD></TR> + </TABLE> -�߂�l�͎w��O�� flag �̒l�ł��B -�����ɐ������Ȃ����̂��w�肳�ꂽ�ꍇ�� nil ���Ԃ�܂��B<BR> +�߂�l�͎w���� flag �̒l�ł��B +�����ɐ��l�ȊO���w�肳�ꂽ�ꍇ�� nil ���Ԃ�܂��B�������Ȃ� ROUND_MODE ���w�肳�ꂽ�Ƃ��� +��������A����� ROUND_MODE ���Ԃ�܂��B<BR> mode ���\�b�h�ł͊ۂߑ���̈ʒu�����[�U���w�肷�邱�Ƃ͂ł��܂���B �ۂߑ���ƈʒu�������Ő��䂵�����ꍇ�� truncate/round/ceil/floor �� -add/sub/mult �Ƃ������C���X�^���X���\�b�h���g�p���ĉ������B +add/sub/mult/div �Ƃ������C���X�^���X���\�b�h���g�p���ĉ������B </BLOCKQUOTE> <LI><B>limit([n])</B></LI><BLOCKQUOTE> ���������BigDecimal�I�u�W�F�N�g�̍ő包����n���ɐ������܂��B @@ -192,7 +196,7 @@ n ���w�肵�Ȃ��ꍇ�́A����̍ő包�����Ԃ�܂��B<BR> �ۂߏ��������s����܂��B �������A���ۂɂ� n ����傫�� �������m�ۂ���܂��B�܂��Alimit �ɂ�錅��������(��������������)�A -�C���X�^���X���\�b�h (truncate/round/ceil/floor/add/sub/mult) ��� +�C���X�^���X���\�b�h (truncate/round/ceil/floor/add/sub/mult/div) ��� �D�悳���̂Œ��ӂ��K�v�ł��B<BR> mf = BigDecimal::limit(n)<BR> </BLOCKQUOTE> @@ -296,8 +300,8 @@ c = BigDecimal("-1.23456").floor # ==> -2 n>=0 �Ȃ�A�����_�ȉ� n+1 �ʂ̐����𑀍삵�܂�(�����_�ȉ����A�ő� n ���ɂ��܂�)�B<BR> n �����̂Ƃ��͏����_�ȏ� n ���ڂ𑀍삵�܂�(�����_�ʒu���獶�ɏ��Ȃ��Ƃ� n �� 0 �����т܂�)�B<BR> <CODE><PRE> - c = BigDecimal::new("1.23456").floor(4) # ==> 1.2345 - c = BigDecimal::new("15.23456").floor(-1) # ==> 10.0 + c = BigDecimal("1.23456").floor(4) # ==> 1.2345 + c = BigDecimal("15.23456").floor(-1) # ==> 10.0 </PRE></CODE> </BLOCKQUOTE> @@ -313,32 +317,35 @@ c = BigDecimal("-1.23456").ceil # ==> -1 n>=0 �Ȃ�A�����_�ȉ� n+1 �ʂ̐����𑀍삵�܂�(�����_�ȉ����A�ő� n ���ɂ��܂�)�B<BR> n �����̂Ƃ��͏����_�ȏ� n ���ڂ��𑀍삵�܂�(�����_�ʒu���獶�ɏ��Ȃ��Ƃ� n �� 0 �����т܂�)�B<BR> <CODE><PRE> - c = BigDecimal::new("1.23456").ceil(4) # ==> 1.2346 - c = BigDecimal::new("15.23456").ceil(-1) # ==> 20.0 + c = BigDecimal("1.23456").ceil(4) # ==> 1.2346 + c = BigDecimal("15.23456").ceil(-1) # ==> 20.0 </PRE></CODE> </BLOCKQUOTE> <LI><B>round[(n[,b])]</B></LI><BLOCKQUOTE> c = a.round<BR> -�����_�ȉ����ʂ̐����l�̌ܓ����Đ����iBigDecimal �l�j�ɂ��܂��B<BR> + +�N���X���\�b�h BigDecimal::mode(BigDecimal::ROUND_MODE,flag) �Ŏw�肵�� +ROUND_MODE �ɏ]���Ċۂߑ�������s���܂��B +BigDecimal::mode(BigDecimal::ROUND_MODE,flag) �ʼn����w�肹���A���A���� +���w�肵�Ȃ��ꍇ�́u�����_�ȉ����ʂ̐����l�̌ܓ����Đ����iBigDecimal �l�j�v�ɂ��܂��B<BR> <CODE><PRE> c = BigDecimal("1.23456").round # ==> 1 c = BigDecimal("-1.23456").round # ==> -1 </PRE></CODE> �ȉ��̂悤�Ɉ�����^���āA�����_�ȉ� n+1 �ʂ̐����𑀍삷�邱�Ƃ��ł��܂��B<BR> -n �����̎��́A�����_�ȉ� n+1 �ʂ̐������l�̌ܓ����܂�(�����_�ȉ����A�ő� n ���ɂ��܂�)�B<BR> -n �����̂Ƃ��͏����_�ȏ� n ���ڂ��𑀍삵�܂�(�����_�ʒu���獶�ɏ��Ȃ��Ƃ� n �� 0 �����т܂�)�B +n �����̎��́A�����_�ȉ� n+1 �ʂ̐������ۂ߂܂�(�����_�ȉ����A�ő� n ���ɂ��܂�)�B<BR> +n �����̂Ƃ��͏����_�ȏ� n ���ڂ��ۂ߂܂�(�����_�ʒu���獶�ɏ��Ȃ��Ƃ� n �� 0 �����т܂�)�B <CODE><PRE> -c = BigDecimal::new("1.23456").round(4) # ==> 1.2346 -c = BigDecimal::new("15.23456").round(-1) # ==> 20.0 +c = BigDecimal("1.23456").round(4) # ==> 1.2346 +c = BigDecimal("15.23456").round(-1) # ==> 20.0 </PRE></CODE> -�Q�Ԗڂ̈����i�f�t�H���g�� 0�j�Ƀ[���ȊO���w�肷��ƁA������ Banker's rounding �ɂȂ�܂��B<BR> - Banker's rounding �Ƃ́A�l�̌ܓ����鐔���� p �Ƃ��āAp < 5 �Ȃ��̂� p > 5 �Ȃ��グ�A -p �����傤�ǂT�̂Ƃ������͐�グ��̐����{�P�������ɂȂ�Ƃ�������グ�܂��B +�Q�Ԗڂ̈������w�肷��ƁABigDecimal#mode �̎w������āA�w�肳�ꂽ���@�� +�ۂߑ�������s���܂��B <CODE><PRE> -c = BigDecimal::new("1.23456").round(3,1) # ==> 1.234 -c = BigDecimal::new("1.23356").round(3,1) # ==> 1.234 +c = BigDecimal("1.23456").round(3,BigDecimal::ROUND_HALF_EVEN) # ==> 1.234 +c = BigDecimal("1.23356").round(3,BigDecimal::ROUND_HALF_EVEN) # ==> 1.234 </PRE></CODE> </BLOCKQUOTE> @@ -349,8 +356,8 @@ c = a.truncate<BR> n �����̎��́A�����_�ȉ� n+1 �ʂ̐������̂Ă܂�(�����_�ȉ����A�ő� n ���ɂ��܂�)�B n �����̂Ƃ��͏����_�ȏ� n ���ڂ��𑀍삵�܂�(�����_�ʒu���獶�ɏ��Ȃ��Ƃ� n �� 0 �����т܂�)�B<BR> <CODE><PRE> -c = BigDecimal::new("1.23456").truncate(4) # ==> 1.2345 -c = BigDecimal::new("15.23456").truncate(-1) # ==> 10.0 +c = BigDecimal("1.23456").truncate(4) # ==> 1.2345 +c = BigDecimal("15.23456").truncate(-1) # ==> 10.0 </PRE></CODE> </BLOCKQUOTE> |