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
This commit is contained in:
Tomasz Sowa 2009-11-24 05:14:54 +00:00
parent 0d1a57bdb4
commit bac79e0bfa
3 changed files with 40 additions and 19 deletions

View File

@ -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: support for wide characters (wchar_t, std::wstring)
* added: Big::IsInteger() * added: Big::IsInteger()
returns true if the value is integer (without fraction) returns true if the value is integer (without fraction)
@ -68,6 +68,8 @@
base 4: 1.3333333333333222 base 4: 1.3333333333333222
base 8: 1.77777777724 base 8: 1.77777777724
base 16: 1.FFFFFFEA 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 * removed: Parser<>::SetFactorialMax() method
the factorial() is such a fast now that we don't need the method longer the factorial() is such a fast now that we don't need the method longer
* removed: ErrorCode::err_too_big_factorial * removed: ErrorCode::err_too_big_factorial

View File

@ -2871,7 +2871,7 @@ public:
uint base = 10, uint base = 10,
bool scient = false, bool scient = false,
sint scient_from = 15, sint scient_from = 15,
sint comma_digits = -1, sint round = -1,
bool trim_zeroes = true, bool trim_zeroes = true,
wchar_t comma = '.' ) const wchar_t comma = '.' ) const
{ {
@ -2880,7 +2880,7 @@ public:
conv.base = base; conv.base = base;
conv.scient = scient; conv.scient = scient;
conv.scient_from = scient_from; conv.scient_from = scient_from;
conv.comma_digits = comma_digits; conv.round = round;
conv.trim_zeroes = trim_zeroes; conv.trim_zeroes = trim_zeroes;
conv.comma = static_cast<uint>(comma); conv.comma = static_cast<uint>(comma);
@ -2896,7 +2896,7 @@ public:
uint base = 10, uint base = 10,
bool scient = false, bool scient = false,
sint scient_from = 15, sint scient_from = 15,
sint comma_digits = -1, sint round = -1,
bool trim_zeroes = true, bool trim_zeroes = true,
wchar_t comma = '.' ) const wchar_t comma = '.' ) const
{ {
@ -2905,7 +2905,7 @@ public:
conv.base = base; conv.base = base;
conv.scient = scient; conv.scient = scient;
conv.scient_from = scient_from; conv.scient_from = scient_from;
conv.comma_digits = comma_digits; conv.round = round;
conv.trim_zeroes = trim_zeroes; conv.trim_zeroes = trim_zeroes;
conv.comma = static_cast<uint>(comma); conv.comma = static_cast<uint>(comma);
@ -3017,7 +3017,7 @@ private:
we're rounding the mantissa only if the base is different from 2,4,8 or 16 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) (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<string_type, char_type>(result, conv, new_exp) ) if( ToString_RoundMantissa<string_type, char_type>(result, conv, new_exp) )
{ {
Misc::AssignString(result, error_overflow_msg); Misc::AssignString(result, error_overflow_msg);
@ -3529,11 +3529,17 @@ private:
if( new_man.length() < 2 ) if( new_man.length() < 2 )
return 0; 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; typename string_type::size_type i = new_man.length() - 1;
// we're erasing the last character // we're erasing the last character
uint digit = Misc::CharToDigit( new_man[i] ); uint digit = Misc::CharToDigit( new_man[i] );
new_man.erase( i, 1 ); new_man.erase(i, 1);
uint carry = new_exp.AddOne(); uint carry = new_exp.AddOne();
// if the last character is greater or equal 'base/2' // if the last character is greater or equal 'base/2'
@ -3813,7 +3819,7 @@ private:
void ToString_CorrectDigitsAfterComma( string_type & new_man, void ToString_CorrectDigitsAfterComma( string_type & new_man,
const Conv & conv ) const const Conv & conv ) const
{ {
if( conv.comma_digits >= 0 ) if( conv.round >= 0 )
ToString_CorrectDigitsAfterComma_Round<string_type, char_type>(new_man, conv); ToString_CorrectDigitsAfterComma_Round<string_type, char_type>(new_man, conv);
if( conv.trim_zeroes ) if( conv.trim_zeroes )
@ -3881,15 +3887,15 @@ private:
// if 'max_digit_after_comma' is greater than 'after_comma' (or equal) // if 'max_digit_after_comma' is greater than 'after_comma' (or equal)
// we don't have anything for cutting // we don't have anything for cutting
if( static_cast<StrSize>(conv.comma_digits) >= after_comma ) if( static_cast<StrSize>(conv.round) >= after_comma )
return; 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 // 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 // we're cutting the comma operator as well
// (it's not needed now because we've cut the whole rest after the comma) // (it's not needed now because we've cut the whole rest after the comma)

View File

@ -321,6 +321,7 @@ namespace ttmath
/*! /*!
this struct is used when converting to/from a string this struct is used when converting to/from a string
/temporarily only in Big::ToString() and Big::FromString()/
*/ */
struct Conv struct Conv
{ {
@ -348,6 +349,21 @@ namespace ttmath
sint scient_from; 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() used only in Big::ToString()
tells how many digits after comma are possible tells how many digits after comma are possible
@ -356,11 +372,11 @@ namespace ttmath
set it to zero if you want integer value only set it to zero if you want integer value only
for example when the value is: for example when the value is:
12.345678 and comma_digit is 4 12.345678 and 'round' is 4
then the result will be then the result will be
12.3457 (the last digit was rounded) 12.3457 (the last digit was rounded)
*/ */
sint comma_digits; sint round;
/*! /*!
@ -404,9 +420,6 @@ namespace ttmath
uint group_exp; // not implemented yet uint group_exp; // not implemented yet
/*!
*/
bool group_multiple; // not implemented yet
Conv() Conv()
@ -415,13 +428,13 @@ namespace ttmath
base = 10; base = 10;
scient = false; scient = false;
scient_from = 15; scient_from = 15;
comma_digits = -1; // !! change to 'round' ? base_round = true;
round = -1;
trim_zeroes = true; trim_zeroes = true;
comma = '.'; comma = '.';
comma2 = ','; comma2 = ',';
group = 0; group = 0;
group_exp = 0; group_exp = 0;
group_multiple = true;
} }
}; };