From bac79e0bfaede70848964a33e36e8a52d63a18bf Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 24 Nov 2009 05:14:54 +0000 Subject: [PATCH] renamed: Conv::comma_digits to Conv::round added: bool Conv::base_round 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) changed: in Big::ToString() some additional rounding (base_round) is now made only when the value is not an integer git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@244 e52654a7-88a9-db11-a3e9-0013d4bc506e --- CHANGELOG | 4 +++- ttmath/ttmathbig.h | 28 +++++++++++++++++----------- ttmath/ttmathtypes.h | 27 ++++++++++++++++++++------- 3 files changed, 40 insertions(+), 19 deletions(-) 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; } };