diff --git a/CHANGELOG b/CHANGELOG index d3bf84d..e201916 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ - Version 0.9.0 prerelease (2009.11.09): +Version 0.9.0 prerelease (2009.11.24): * added: support for wide characters (wchar_t, std::wstring) * added: Big::IsInteger() returns true if the value is integer (without fraction) @@ -68,6 +68,8 @@ base 4: 1.3333333333333222 base 8: 1.77777777724 base 16: 1.FFFFFFEA + * changed: in Big::ToString() some additional rounding (base_round) is now made only + when the value is not an integer * removed: Parser<>::SetFactorialMax() method the factorial() is such a fast now that we don't need the method longer * removed: ErrorCode::err_too_big_factorial diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index ff1ec91..819cae1 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -2871,7 +2871,7 @@ public: uint base = 10, bool scient = false, sint scient_from = 15, - sint comma_digits = -1, + sint round = -1, bool trim_zeroes = true, wchar_t comma = '.' ) const { @@ -2880,7 +2880,7 @@ public: conv.base = base; conv.scient = scient; conv.scient_from = scient_from; - conv.comma_digits = comma_digits; + conv.round = round; conv.trim_zeroes = trim_zeroes; conv.comma = static_cast(comma); @@ -2896,7 +2896,7 @@ public: uint base = 10, bool scient = false, sint scient_from = 15, - sint comma_digits = -1, + sint round = -1, bool trim_zeroes = true, wchar_t comma = '.' ) const { @@ -2905,7 +2905,7 @@ public: conv.base = base; conv.scient = scient; conv.scient_from = scient_from; - conv.comma_digits = comma_digits; + conv.round = round; conv.trim_zeroes = trim_zeroes; conv.comma = static_cast(comma); @@ -3017,7 +3017,7 @@ private: we're rounding the mantissa only if the base is different from 2,4,8 or 16 (this formula means that the number of bits in the base is greater than one) */ - if( conv.base!=2 && conv.base!=4 && conv.base!=8 && conv.base!=16 ) + if( conv.base_round && conv.base!=2 && conv.base!=4 && conv.base!=8 && conv.base!=16 ) if( ToString_RoundMantissa(result, conv, new_exp) ) { Misc::AssignString(result, error_overflow_msg); @@ -3529,11 +3529,17 @@ private: if( new_man.length() < 2 ) return 0; + // the rounding is only made when new_exp is less than zero + // if new_exp is greater or equal zero then the value is integer and + // don't have to be rounded + if( !new_exp.IsSign() ) + return 0; + typename string_type::size_type i = new_man.length() - 1; // we're erasing the last character uint digit = Misc::CharToDigit( new_man[i] ); - new_man.erase( i, 1 ); + new_man.erase(i, 1); uint carry = new_exp.AddOne(); // if the last character is greater or equal 'base/2' @@ -3813,7 +3819,7 @@ private: void ToString_CorrectDigitsAfterComma( string_type & new_man, const Conv & conv ) const { - if( conv.comma_digits >= 0 ) + if( conv.round >= 0 ) ToString_CorrectDigitsAfterComma_Round(new_man, conv); if( conv.trim_zeroes ) @@ -3881,15 +3887,15 @@ private: // if 'max_digit_after_comma' is greater than 'after_comma' (or equal) // we don't have anything for cutting - if( static_cast(conv.comma_digits) >= after_comma ) + if( static_cast(conv.round) >= after_comma ) return; - uint last_digit = Misc::CharToDigit( new_man[ index + conv.comma_digits + 1 ], conv.base ); + uint last_digit = Misc::CharToDigit( new_man[ index + conv.round + 1 ], conv.base ); // we're cutting the rest of the string - new_man.erase(index + conv.comma_digits + 1, after_comma - conv.comma_digits); + new_man.erase(index + conv.round + 1, after_comma - conv.round); - if( conv.comma_digits == 0 ) + if( conv.round == 0 ) { // we're cutting the comma operator as well // (it's not needed now because we've cut the whole rest after the comma) diff --git a/ttmath/ttmathtypes.h b/ttmath/ttmathtypes.h index 67f0639..58817e9 100644 --- a/ttmath/ttmathtypes.h +++ b/ttmath/ttmathtypes.h @@ -321,6 +321,7 @@ namespace ttmath /*! this struct is used when converting to/from a string + /temporarily only in Big::ToString() and Big::FromString()/ */ struct Conv { @@ -348,6 +349,21 @@ namespace ttmath sint scient_from; + /*! + if 'base_round' is true and 'base' is different from 2, 4, 8, or 16 + and the result value is not an integer then we make an additional rounding + (after converting the last digit from the result is skipped) + default: true + + e.g. + Conv c; + c.base_round = false; + Big<1, 1> a = "0.1"; // decimal input + std::cout << a.ToString(c) << std::endl; // the result is: 0.099999999 + */ + bool base_round; + + /*! used only in Big::ToString() tells how many digits after comma are possible @@ -356,11 +372,11 @@ namespace ttmath set it to zero if you want integer value only for example when the value is: - 12.345678 and comma_digit is 4 + 12.345678 and 'round' is 4 then the result will be 12.3457 (the last digit was rounded) */ - sint comma_digits; + sint round; /*! @@ -404,9 +420,6 @@ namespace ttmath uint group_exp; // not implemented yet - /*! - */ - bool group_multiple; // not implemented yet Conv() @@ -415,13 +428,13 @@ namespace ttmath base = 10; scient = false; scient_from = 15; - comma_digits = -1; // !! change to 'round' ? + base_round = true; + round = -1; trim_zeroes = true; comma = '.'; comma2 = ','; group = 0; group_exp = 0; - group_multiple = true; } };