diff --git a/CHANGELOG b/CHANGELOG index fc37261..ad45d2c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,13 @@ -Version 0.9.1 prerelease (2009.12.05): +Version 0.9.1 prerelease (2009.12.06): * fixed: the parser didn't use characters for changing the base (# and &) those characters were skipped (this bug was introduced in 0.9.0) + * added: IEEE 754 half-to-even rounding (bankers' rounding) to the following + floating point algorithms: + Big::Add + Big::Sub + Big::Mul + Big::Div * added: to Big::ToString() - additional rounding when conv.base_round is used if the value is not an integer we calculate how many valid digits there are after the comma operator (in conv.base radix) and then we skipped the rest diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index 758d3ef..13f38fc 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -714,7 +714,36 @@ public: +private: + /*! + this method does the half-to-even rounding (banker's rounding) + + if is_half is: + true - that means the rest was equal the half (0.5 decimal) + false - that means the rest was greater than a half (greater than 0.5 decimal) + + if the rest was less than a half then don't call this method + (the rounding should does nothing then) + */ + uint RoundHalfToEven(bool is_half) + { + uint c = 0; + + if( !is_half || mantissa.IsTheLowestBitSet() ) + { + if( mantissa.AddOne() ) + { + mantissa.Rcr(1, 1); + c = exponent.AddOne(); + } + } + + return c; + } + + +public: /*! * @@ -772,8 +801,11 @@ public: // values have the same signs if( mantissa.Add(ss2.mantissa) ) { - mantissa.Rcr(1,1); - c = exponent.AddOne(); + bool is_exact_half = mantissa.Rcr(1,1); + c += exponent.AddOne(); + + if( is_exact_half ) + c += RoundHalfToEven(is_exact_half); } } else @@ -1078,6 +1110,41 @@ public: } +private: + + + /*! + this method checks whether a table pointed by 'tab' and 'len' + has the value 0.5 decimal + (it is treated as the comma operator would be before the highest bit) + call this method only if the highest bit is set - you have to test it beforehand + + return: + true - tab was equal the half (0.5 decimal) + false - tab was greater than a half (greater than 0.5 decimal) + + */ + bool CheckGreaterOrEqualHalf(uint * tab, uint len) + { + uint i; + + TTMATH_ASSERT( len>0 && (tab[len-1] & TTMATH_UINT_HIGHEST_BIT)!=0 ) + + for(i=0 ; i man_result; - uint i,c; + uint c = 0; + uint i; if( IsNan() || ss2.IsNan() ) return CheckCarry(1); @@ -1110,13 +1178,22 @@ public: // if there is a zero value in man_result the method CompensationToLeft() // returns 0 but we'll correct this at the end in Standardizing() method) i = man_result.CompensationToLeft(); - - c = exponent.Add( man * TTMATH_BITS_PER_UINT - i ); + uint exp_add = man * TTMATH_BITS_PER_UINT - i; + + if( exp_add ) + c += exponent.Add( exp_add ); + c += exponent.Add( ss2.exponent ); for(i=0 ; i(conv.group) ) continue;