added: struct: Conv
consists of some parameters used in ToString() and FromString() added: Big::ToString() can group digits e.g. 1234567 -> 1`234`567 added: Parser::SetGroup(int g) Parser::SetComma(int c, int c2 = 0) Parser::SetParamSep(int s) added: uint Big::ToString(std::string & result, const Conv & conv) uint Big::ToString(std::wstring & result, const Conv & conv) std::string Big::ToString(const Conv & conv) const std::string Big::ToString() added: uint FromString(const char * source, const Conv & conv, const char **, bool *) uint FromString(const wchar_t * source, const Conv & conv, const wchar_t **, bool *) uint FromString(const std::string & string, const Conv & conv, const wchar_t **, bool *) uint FromString(const std::wstring & string, const Conv & conv, const wchar_t **, bool *) removed: macros: TTMATH_COMMA_CHARACTER_1 and TTMATH_COMMA_CHARACTER_2 the comma characters we have in Conv struct now git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@226 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
parent
413c83de45
commit
2feabc64e2
20
CHANGELOG
20
CHANGELOG
|
@ -1,4 +1,4 @@
|
|||
Version 0.9.0 prerelease (2009.10.25):
|
||||
Version 0.9.0 prerelease (2009.11.01):
|
||||
* added: support for wide characters (wchar_t, std::wstring)
|
||||
* added: Big::IsInteger()
|
||||
returns true if the value is integer (without fraction)
|
||||
|
@ -28,6 +28,22 @@ Version 0.9.0 prerelease (2009.10.25):
|
|||
(at least one mathematical operator was used or a function or variable)
|
||||
* added: to the parser: operator percentage
|
||||
e.g. 1000-50%=1000-(1000*0,5)=500
|
||||
* added: struct: Conv
|
||||
consists of some parameters used
|
||||
in ToString() and FromString()
|
||||
* added: Big::ToString() can group digits
|
||||
e.g. 1234567 -> 1`234`567
|
||||
* added: Parser::SetGroup(int g)
|
||||
Parser::SetComma(int c, int c2 = 0)
|
||||
Parser::SetParamSep(int s)
|
||||
* added: uint Big::ToString(std::string & result, const Conv & conv)
|
||||
uint Big::ToString(std::wstring & result, const Conv & conv)
|
||||
std::string Big::ToString(const Conv & conv) const
|
||||
std::string Big::ToString()
|
||||
* added: uint FromString(const char * source, const Conv & conv, const char **, bool *)
|
||||
uint FromString(const wchar_t * source, const Conv & conv, const wchar_t **, bool *)
|
||||
uint FromString(const std::string & string, const Conv & conv, const wchar_t **, bool *)
|
||||
uint FromString(const std::wstring & string, const Conv & conv, const wchar_t **, bool *)
|
||||
* changed: Factorial() is using the Gamma() function now
|
||||
* changed: Big::Div(ss2)
|
||||
Big::Mod(ss2)
|
||||
|
@ -36,6 +52,8 @@ Version 0.9.0 prerelease (2009.10.25):
|
|||
* 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
|
||||
* removed: macros: TTMATH_COMMA_CHARACTER_1 and TTMATH_COMMA_CHARACTER_2
|
||||
the comma characters we have in Conv struct now
|
||||
|
||||
|
||||
Version 0.8.6 (2009.10.25):
|
||||
|
|
|
@ -2809,82 +2809,114 @@ public:
|
|||
|
||||
|
||||
/*!
|
||||
a method for converting the value into a string with a base equal 'base'
|
||||
|
||||
input:
|
||||
* base - a base (radix) on which the value will be shown
|
||||
|
||||
* if 'always_scientific' is true the result will be shown in 'scientific' mode
|
||||
if 'always_scientific' is false the result will be shown
|
||||
either as 'scientific' or 'normal' mode, it depends whether the abs(exponent)
|
||||
is greater than 'when_scientific' or not, if it's greater the value
|
||||
will be printed as 'scientific'
|
||||
|
||||
* 'max_digit_after_comma' - rounding
|
||||
if 'max_digit_after_comma' is equal -1 that all digits in the mantissa
|
||||
will be printed
|
||||
if 'max_digit_after_comma' is equal or greater than zero
|
||||
that only 'max_digit_after_comma' after the comma operator will be shown
|
||||
(if 'max_digit_after_comma' is equal zero there'll be shown only
|
||||
integer value without the comma)
|
||||
for example when the value is:
|
||||
12.345678 and max_digit_after_comma is 4
|
||||
then the result will be
|
||||
12.3457 (the last digit was rounded)
|
||||
if there isn't the comma operator (when the value is too big and we're printing
|
||||
it not as scientific) 'max_digit_after_comma' will be ignored
|
||||
|
||||
* if 'remove_trailing_zeroes' is true that not mattered digits
|
||||
in the mantissa will be cut off
|
||||
(zero characters at the end -- after the comma operator)
|
||||
|
||||
* decimal_point - a character which will be used as a decimal point
|
||||
a method for converting into a string
|
||||
struct Conv is defined in ttmathtypes.h, look there for more information about parameters
|
||||
|
||||
output:
|
||||
return value:
|
||||
0 - ok and 'result' will be an object of type std::string (or std::wstring) which holds the value
|
||||
1 - if there was a carry (shoudn't be in a normal situation - if is that means there
|
||||
1 - if there is a carry (it shoudn't be in a normal situation - if it is that means there
|
||||
is somewhere an error in the library)
|
||||
*/
|
||||
uint ToString( std::string & result,
|
||||
uint base = 10,
|
||||
bool always_scientific = false,
|
||||
sint when_scientific = 15,
|
||||
sint max_digit_after_comma = -1,
|
||||
bool remove_trailing_zeroes = true,
|
||||
char decimal_point = TTMATH_COMMA_CHARACTER_1 ) const
|
||||
uint base = 10,
|
||||
bool scient = false,
|
||||
sint scient_from = 15,
|
||||
sint comma_digits = -1,
|
||||
bool trim_zeroes = true,
|
||||
wchar_t comma = '.' ) const
|
||||
{
|
||||
return ToStringBase(result, base, always_scientific, when_scientific,
|
||||
max_digit_after_comma, remove_trailing_zeroes, decimal_point);
|
||||
Conv conv;
|
||||
|
||||
conv.base = base;
|
||||
conv.scient = scient;
|
||||
conv.scient_from = scient_from;
|
||||
conv.comma_digits = comma_digits;
|
||||
conv.trim_zeroes = trim_zeroes;
|
||||
conv.comma = static_cast<uint>(comma);
|
||||
|
||||
return ToStringBase<std::string, char>(result, conv);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting the value into a string with a base equal 'base'
|
||||
a method for converting into a string
|
||||
struct Conv is defined in ttmathtypes.h, look there for more information about parameters
|
||||
*/
|
||||
uint ToString( std::wstring & result,
|
||||
uint base = 10,
|
||||
bool always_scientific = false,
|
||||
sint when_scientific = 15,
|
||||
sint max_digit_after_comma = -1,
|
||||
bool remove_trailing_zeroes = true,
|
||||
wchar_t decimal_point = TTMATH_COMMA_CHARACTER_1 ) const
|
||||
uint base = 10,
|
||||
bool scient = false,
|
||||
sint scient_from = 15,
|
||||
sint comma_digits = -1,
|
||||
bool trim_zeroes = true,
|
||||
wchar_t comma = '.' ) const
|
||||
{
|
||||
return ToStringBase(result, base, always_scientific, when_scientific,
|
||||
max_digit_after_comma, remove_trailing_zeroes, decimal_point);
|
||||
Conv conv;
|
||||
|
||||
conv.base = base;
|
||||
conv.scient = scient;
|
||||
conv.scient_from = scient_from;
|
||||
conv.comma_digits = comma_digits;
|
||||
conv.trim_zeroes = trim_zeroes;
|
||||
conv.comma = static_cast<uint>(comma);
|
||||
|
||||
return ToStringBase<std::wstring, wchar_t>(result, conv);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting into a string
|
||||
struct Conv is defined in ttmathtypes.h, look there for more information about parameters
|
||||
*/
|
||||
uint ToString(std::string & result, const Conv & conv) const
|
||||
{
|
||||
return ToStringBase<std::string, char>(result, conv);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting into a string
|
||||
struct Conv is defined in ttmathtypes.h, look there for more information about parameters
|
||||
*/
|
||||
uint ToString(std::wstring & result, const Conv & conv) const
|
||||
{
|
||||
return ToStringBase<std::wstring, wchar_t>(result, conv);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting into a string
|
||||
struct Conv is defined in ttmathtypes.h, look there for more information about parameters
|
||||
*/
|
||||
std::string ToString(const Conv & conv) const
|
||||
{
|
||||
std::string result;
|
||||
ToStringBase<std::string, char>(result, conv);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting into a string
|
||||
struct Conv is defined in ttmathtypes.h, look there for more information about parameters
|
||||
*/
|
||||
std::string ToString() const
|
||||
{
|
||||
Conv conv;
|
||||
|
||||
return ToString(conv);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
/*!
|
||||
an auxiliary method for converting into the string
|
||||
*/
|
||||
template<class string_type, class char_type>
|
||||
uint ToStringBase( string_type & result,
|
||||
uint base,
|
||||
bool always_scientific,
|
||||
sint when_scientific,
|
||||
sint max_digit_after_comma,
|
||||
bool remove_trailing_zeroes,
|
||||
char_type decimal_point) const
|
||||
uint ToStringBase(string_type & result, const Conv & conv) const
|
||||
{
|
||||
static char error_overflow_msg[] = "overflow";
|
||||
static char error_nan_msg[] = "NaN";
|
||||
|
@ -2896,7 +2928,7 @@ private:
|
|||
return 0;
|
||||
}
|
||||
|
||||
if( base<2 || base>16 )
|
||||
if( conv.base<2 || conv.base>16 )
|
||||
{
|
||||
Misc::AssignString(result, error_overflow_msg);
|
||||
return 1;
|
||||
|
@ -2926,7 +2958,7 @@ private:
|
|||
*/
|
||||
Int<exp+1> new_exp;
|
||||
|
||||
if( ToString_CreateNewMantissaAndExponent(result, base, new_exp) )
|
||||
if( ToString_CreateNewMantissaAndExponent(result, conv, new_exp) )
|
||||
{
|
||||
Misc::AssignString(result, error_overflow_msg);
|
||||
return 1;
|
||||
|
@ -2936,16 +2968,14 @@ 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( base!=2 && base!=4 && base!=8 && base!=16 )
|
||||
if( ToString_RoundMantissa(result, base, new_exp, decimal_point) )
|
||||
if( conv.base!=2 && conv.base!=4 && conv.base!=8 && conv.base!=16 )
|
||||
if( ToString_RoundMantissa<string_type, char_type>(result, conv, new_exp) )
|
||||
{
|
||||
Misc::AssignString(result, error_overflow_msg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( ToString_SetCommaAndExponent( result, base, new_exp, always_scientific,
|
||||
when_scientific, max_digit_after_comma,
|
||||
remove_trailing_zeroes, decimal_point ) )
|
||||
if( ToString_SetCommaAndExponent<string_type, char_type>(result, conv, new_exp) )
|
||||
{
|
||||
Misc::AssignString(result, error_overflow_msg);
|
||||
return 1;
|
||||
|
@ -2959,8 +2989,6 @@ private:
|
|||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
/*!
|
||||
in the method 'ToString_CreateNewMantissaAndExponent()' we're using
|
||||
|
@ -2971,7 +2999,7 @@ private:
|
|||
|
||||
|
||||
/*!
|
||||
an auxiliary method for converting into the string (private)
|
||||
an auxiliary method for converting into the string
|
||||
|
||||
input:
|
||||
base - the base in range <2,16>
|
||||
|
@ -3030,16 +3058,16 @@ private:
|
|||
new_exp = [log base (2^exponent)] + 1 <- where [x] means integer value from x
|
||||
*/
|
||||
template<class string_type>
|
||||
uint ToString_CreateNewMantissaAndExponent( string_type & new_man, uint base,
|
||||
uint ToString_CreateNewMantissaAndExponent( string_type & new_man, const Conv & conv,
|
||||
Int<exp+1> & new_exp) const
|
||||
{
|
||||
uint c = 0;
|
||||
|
||||
if(base<2 || base>16)
|
||||
if( conv.base<2 || conv.base>16 )
|
||||
return 1;
|
||||
|
||||
// the speciality for base equal 2
|
||||
if( base == 2 )
|
||||
if( conv.base == 2 )
|
||||
return ToString_CreateNewMantissaAndExponent_Base2(new_man, new_exp);
|
||||
|
||||
// this = mantissa * 2^exponent
|
||||
|
@ -3054,7 +3082,7 @@ private:
|
|||
|
||||
// new_exp_ = [log base (2^exponent)] + 1
|
||||
Big<exp+1,man> new_exp_;
|
||||
c += new_exp_.ToString_Log(temp, base); // this logarithm isn't very complicated
|
||||
c += new_exp_.ToString_Log(temp, conv.base); // this logarithm isn't very complicated
|
||||
new_exp_.SkipFraction();
|
||||
temp.SetOne();
|
||||
c += new_exp_.Add( temp );
|
||||
|
@ -3067,7 +3095,7 @@ private:
|
|||
c += new_exp_.ToInt(new_exp);
|
||||
|
||||
// base_ = base
|
||||
Big<exp+1,man> base_(base);
|
||||
Big<exp+1,man> base_(conv.base);
|
||||
|
||||
// base_ = base_ ^ new_exp_
|
||||
c += base_.Pow( new_exp_ );
|
||||
|
@ -3089,7 +3117,7 @@ private:
|
|||
// (temp.Div( base_ )) the value of exponent should be equal zero or
|
||||
// minimum smaller than zero then we've got the mantissa which has
|
||||
// maximum valid bits
|
||||
temp.mantissa.ToString(new_man, base);
|
||||
temp.mantissa.ToString(new_man, conv.base);
|
||||
|
||||
// because we had used a bigger type for calculating I think we
|
||||
// shouldn't have had a carry
|
||||
|
@ -3307,7 +3335,7 @@ private:
|
|||
(it's used in systems where the base is different from 2)
|
||||
*/
|
||||
template<class string_type, class char_type>
|
||||
uint ToString_RoundMantissa(string_type & new_man, uint base, Int<exp+1> & new_exp, char_type decimal_point) const
|
||||
uint ToString_RoundMantissa(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const
|
||||
{
|
||||
// we must have minimum two characters
|
||||
if( new_man.length() < 2 )
|
||||
|
@ -3322,8 +3350,8 @@ private:
|
|||
|
||||
// if the last character is greater or equal 'base/2'
|
||||
// we'll add one into the new mantissa
|
||||
if( digit >= base / 2 )
|
||||
ToString_RoundMantissa_AddOneIntoMantissa(new_man, base, decimal_point);
|
||||
if( digit >= conv.base / 2 )
|
||||
ToString_RoundMantissa_AddOneIntoMantissa<string_type, char_type>(new_man, conv);
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
@ -3335,7 +3363,7 @@ private:
|
|||
this method addes one into the new mantissa
|
||||
*/
|
||||
template<class string_type, class char_type>
|
||||
void ToString_RoundMantissa_AddOneIntoMantissa(string_type & new_man, uint base, char_type decimal_point) const
|
||||
void ToString_RoundMantissa_AddOneIntoMantissa(string_type & new_man, const Conv & conv) const
|
||||
{
|
||||
if( new_man.empty() )
|
||||
return;
|
||||
|
@ -3348,13 +3376,13 @@ private:
|
|||
// we can have the comma as well because
|
||||
// we're using this method later in ToString_CorrectDigitsAfterComma_Round()
|
||||
// (we're only ignoring it)
|
||||
if( new_man[i] == decimal_point )
|
||||
if( new_man[i] == static_cast<char_type>(conv.comma) )
|
||||
continue;
|
||||
|
||||
// we're adding one
|
||||
uint digit = Misc::CharToDigit( new_man[i] ) + 1;
|
||||
|
||||
if( digit == base )
|
||||
if( digit == conv.base )
|
||||
digit = 0;
|
||||
else
|
||||
was_carry = false;
|
||||
|
@ -3374,13 +3402,7 @@ private:
|
|||
into the string
|
||||
*/
|
||||
template<class string_type, class char_type>
|
||||
uint ToString_SetCommaAndExponent( string_type & new_man, uint base,
|
||||
Int<exp+1> & new_exp,
|
||||
bool always_scientific,
|
||||
sint when_scientific,
|
||||
sint max_digit_after_comma,
|
||||
bool remove_trailing_zeroes,
|
||||
char_type decimal_point) const
|
||||
uint ToString_SetCommaAndExponent(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const
|
||||
{
|
||||
uint carry = 0;
|
||||
|
||||
|
@ -3399,18 +3421,19 @@ private:
|
|||
// there shouldn't have been a carry because we're using
|
||||
// a greater type -- 'Int<exp+1>' instead of 'Int<exp>'
|
||||
|
||||
if( !always_scientific )
|
||||
bool print_scientific = conv.scient;
|
||||
|
||||
if( !print_scientific )
|
||||
{
|
||||
if( scientific_exp > when_scientific || scientific_exp < -sint(when_scientific) )
|
||||
always_scientific = true;
|
||||
if( scientific_exp > conv.scient_from || scientific_exp < -sint(conv.scient_from) )
|
||||
print_scientific = true;
|
||||
}
|
||||
|
||||
// 'always_scientific' could be changed
|
||||
if( !always_scientific )
|
||||
ToString_SetCommaAndExponent_Normal(new_man, base, new_exp, max_digit_after_comma, remove_trailing_zeroes, decimal_point);
|
||||
if( !print_scientific )
|
||||
ToString_SetCommaAndExponent_Normal<string_type, char_type>(new_man, conv, new_exp);
|
||||
else
|
||||
// we're passing the 'scientific_exp' instead of 'new_exp' here
|
||||
ToString_SetCommaAndExponent_Scientific(new_man, base, scientific_exp, max_digit_after_comma, remove_trailing_zeroes, decimal_point);
|
||||
ToString_SetCommaAndExponent_Scientific<string_type, char_type>(new_man, conv, scientific_exp);
|
||||
|
||||
return (carry==0)? 0 : 1;
|
||||
}
|
||||
|
@ -3420,25 +3443,22 @@ private:
|
|||
an auxiliary method for converting into the string
|
||||
*/
|
||||
template<class string_type, class char_type>
|
||||
void ToString_SetCommaAndExponent_Normal(
|
||||
string_type & new_man,
|
||||
uint base,
|
||||
Int<exp+1> & new_exp,
|
||||
sint max_digit_after_comma,
|
||||
bool remove_trailing_zeroes,
|
||||
char_type decimal_point) const
|
||||
void ToString_SetCommaAndExponent_Normal(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp ) const
|
||||
{
|
||||
if( !new_exp.IsSign() ) //if( new_exp >= 0 )
|
||||
return ToString_SetCommaAndExponent_Normal_AddingZero(new_man, new_exp);
|
||||
if( !new_exp.IsSign() ) // it means: if( new_exp >= 0 )
|
||||
ToString_SetCommaAndExponent_Normal_AddingZero<string_type, char_type>(new_man, new_exp);
|
||||
else
|
||||
return ToString_SetCommaAndExponent_Normal_SetCommaInside(new_man, base, new_exp, max_digit_after_comma, remove_trailing_zeroes, decimal_point);
|
||||
ToString_SetCommaAndExponent_Normal_SetCommaInside<string_type, char_type>(new_man, conv, new_exp);
|
||||
|
||||
|
||||
ToString_Group_man<string_type, char_type>(new_man, conv);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
an auxiliary method for converting into the string
|
||||
*/
|
||||
template<class string_type>
|
||||
template<class string_type, class char_type>
|
||||
void ToString_SetCommaAndExponent_Normal_AddingZero(string_type & new_man,
|
||||
Int<exp+1> & new_exp) const
|
||||
{
|
||||
|
@ -3460,12 +3480,9 @@ private:
|
|||
*/
|
||||
template<class string_type, class char_type>
|
||||
void ToString_SetCommaAndExponent_Normal_SetCommaInside(
|
||||
string_type & new_man,
|
||||
uint base,
|
||||
Int<exp+1> & new_exp,
|
||||
sint max_digit_after_comma,
|
||||
bool remove_trailing_zeroes,
|
||||
char_type decimal_point) const
|
||||
string_type & new_man,
|
||||
const Conv & conv,
|
||||
Int<exp+1> & new_exp ) const
|
||||
{
|
||||
// new_exp is < 0
|
||||
|
||||
|
@ -3477,7 +3494,7 @@ private:
|
|||
// we're setting the comma within the mantissa
|
||||
|
||||
sint index = new_man_len - e;
|
||||
new_man.insert( new_man.begin() + index, decimal_point);
|
||||
new_man.insert( new_man.begin() + index, static_cast<char_type>(conv.comma));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3486,11 +3503,11 @@ private:
|
|||
uint how_many = e - new_man_len;
|
||||
string_type man_temp(how_many+1, '0');
|
||||
|
||||
man_temp.insert( man_temp.begin()+1, decimal_point);
|
||||
man_temp.insert( man_temp.begin()+1, static_cast<char_type>(conv.comma));
|
||||
new_man.insert(0, man_temp);
|
||||
}
|
||||
|
||||
ToString_CorrectDigitsAfterComma(new_man, base, max_digit_after_comma, remove_trailing_zeroes, decimal_point);
|
||||
ToString_CorrectDigitsAfterComma<string_type, char_type>(new_man, conv);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3499,20 +3516,18 @@ private:
|
|||
*/
|
||||
template<class string_type, class char_type>
|
||||
void ToString_SetCommaAndExponent_Scientific( string_type & new_man,
|
||||
uint base,
|
||||
Int<exp+1> & scientific_exp,
|
||||
sint max_digit_after_comma,
|
||||
bool remove_trailing_zeroes,
|
||||
char_type decimal_point) const
|
||||
const Conv & conv,
|
||||
Int<exp+1> & scientific_exp ) const
|
||||
{
|
||||
if( new_man.empty() )
|
||||
return;
|
||||
|
||||
new_man.insert( new_man.begin()+1, decimal_point );
|
||||
new_man.insert( new_man.begin()+1, static_cast<char_type>(conv.comma) );
|
||||
|
||||
ToString_CorrectDigitsAfterComma(new_man, base, max_digit_after_comma, remove_trailing_zeroes, decimal_point);
|
||||
ToString_CorrectDigitsAfterComma<string_type, char_type>(new_man, conv);
|
||||
ToString_Group_man<string_type, char_type>(new_man, conv);
|
||||
|
||||
if( base == 10 )
|
||||
if( conv.base == 10 )
|
||||
{
|
||||
new_man += 'e';
|
||||
|
||||
|
@ -3527,7 +3542,7 @@ private:
|
|||
}
|
||||
|
||||
string_type temp_exp;
|
||||
scientific_exp.ToString( temp_exp, base );
|
||||
scientific_exp.ToString( temp_exp, conv.base );
|
||||
|
||||
new_man += temp_exp;
|
||||
}
|
||||
|
@ -3537,17 +3552,84 @@ private:
|
|||
an auxiliary method for converting into the string
|
||||
*/
|
||||
template<class string_type, class char_type>
|
||||
void ToString_CorrectDigitsAfterComma( string_type & new_man,
|
||||
uint base,
|
||||
sint max_digit_after_comma,
|
||||
bool remove_trailing_zeroes,
|
||||
char_type decimal_point) const
|
||||
void ToString_Group_man(string_type & new_man, const Conv & conv) const
|
||||
{
|
||||
if( max_digit_after_comma >= 0 )
|
||||
ToString_CorrectDigitsAfterComma_Round(new_man, base, max_digit_after_comma, decimal_point);
|
||||
typedef typename string_type::size_type StrSize;
|
||||
|
||||
if( remove_trailing_zeroes )
|
||||
ToString_CorrectDigitsAfterComma_CutOffZeroCharacters(new_man, decimal_point);
|
||||
if( conv.group == 0 )
|
||||
return;
|
||||
|
||||
// first we're looking for the comma operator
|
||||
StrSize index = new_man.find(static_cast<char_type>(conv.comma), 0);
|
||||
|
||||
if( index == string_type::npos )
|
||||
index = new_man.size();
|
||||
|
||||
ToString_Group_man_before_comma<string_type, char_type>(new_man, conv, index);
|
||||
ToString_Group_man_after_comma<string_type, char_type>(new_man, conv, index+1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
an auxiliary method for converting into the string
|
||||
*/
|
||||
template<class string_type, class char_type>
|
||||
void ToString_Group_man_before_comma( string_type & new_man, const Conv & conv,
|
||||
typename string_type::size_type & index) const
|
||||
{
|
||||
typedef typename string_type::size_type StrSize;
|
||||
uint group = 0;
|
||||
|
||||
StrSize i = index;
|
||||
|
||||
// adding group characters before the comma operator
|
||||
// i>0 because on the first position we don't put any additional grouping characters
|
||||
for( ; i>0 ; --i, ++group)
|
||||
{
|
||||
if( group >= 3 )
|
||||
{
|
||||
group = 0;
|
||||
new_man.insert(i, 1, static_cast<char_type>(conv.group));
|
||||
++index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
an auxiliary method for converting into the string
|
||||
*/
|
||||
template<class string_type, class char_type>
|
||||
void ToString_Group_man_after_comma(string_type & new_man, const Conv & conv,
|
||||
typename string_type::size_type index) const
|
||||
{
|
||||
uint group = 0;
|
||||
|
||||
for( ; index<new_man.size() ; ++index, ++group)
|
||||
{
|
||||
if( group >= 3 )
|
||||
{
|
||||
group = 0;
|
||||
new_man.insert(index, 1, static_cast<char_type>(conv.group));
|
||||
++index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
an auxiliary method for converting into the string
|
||||
*/
|
||||
template<class string_type, class char_type>
|
||||
void ToString_CorrectDigitsAfterComma( string_type & new_man,
|
||||
const Conv & conv ) const
|
||||
{
|
||||
if( conv.comma_digits >= 0 )
|
||||
ToString_CorrectDigitsAfterComma_Round<string_type, char_type>(new_man, conv);
|
||||
|
||||
if( conv.trim_zeroes )
|
||||
ToString_CorrectDigitsAfterComma_CutOffZeroCharacters<string_type, char_type>(new_man, conv);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3557,7 +3639,7 @@ private:
|
|||
template<class string_type, class char_type>
|
||||
void ToString_CorrectDigitsAfterComma_CutOffZeroCharacters(
|
||||
string_type & new_man,
|
||||
char_type decimal_point) const
|
||||
const Conv & conv) const
|
||||
{
|
||||
// minimum two characters
|
||||
if( new_man.length() < 2 )
|
||||
|
@ -3575,12 +3657,12 @@ private:
|
|||
// we must have a comma
|
||||
// (the comma can be removed by ToString_CorrectDigitsAfterComma_Round
|
||||
// which is called before)
|
||||
if( new_man.find_last_of(decimal_point, i) == string_type::npos )
|
||||
if( new_man.find_last_of(static_cast<char_type>(conv.comma), i) == string_type::npos )
|
||||
return;
|
||||
|
||||
// if directly before the first zero is the comma operator
|
||||
// we're cutting it as well
|
||||
if( i>0 && new_man[i]==decimal_point )
|
||||
if( i>0 && new_man[i]==static_cast<char_type>(conv.comma) )
|
||||
--i;
|
||||
|
||||
new_man.erase(i+1, new_man.length()-i-1);
|
||||
|
@ -3593,12 +3675,12 @@ private:
|
|||
template<class string_type, class char_type>
|
||||
void ToString_CorrectDigitsAfterComma_Round(
|
||||
string_type & new_man,
|
||||
uint base,
|
||||
sint max_digit_after_comma,
|
||||
char_type decimal_point) const
|
||||
const Conv & conv ) const
|
||||
{
|
||||
typedef typename string_type::size_type StrSize;
|
||||
|
||||
// first we're looking for the comma operator
|
||||
typename string_type::size_type index = new_man.find(decimal_point, 0);
|
||||
StrSize index = new_man.find(static_cast<char_type>(conv.comma), 0);
|
||||
|
||||
if( index == string_type::npos )
|
||||
// nothing was found (actually there can't be this situation)
|
||||
|
@ -3607,45 +3689,141 @@ private:
|
|||
// we're calculating how many digits there are at the end (after the comma)
|
||||
// 'after_comma' will be greater than zero because at the end
|
||||
// we have at least one digit
|
||||
typename string_type::size_type after_comma = new_man.length() - index - 1;
|
||||
StrSize after_comma = new_man.length() - index - 1;
|
||||
|
||||
// if 'max_digit_after_comma' is greater than 'after_comma' (or equal)
|
||||
// we don't have anything for cutting
|
||||
if( static_cast<typename string_type::size_type>(max_digit_after_comma) >= after_comma )
|
||||
if( static_cast<StrSize>(conv.comma_digits) >= after_comma )
|
||||
return;
|
||||
|
||||
uint last_digit = Misc::CharToDigit( new_man[ index + max_digit_after_comma + 1 ], base );
|
||||
uint last_digit = Misc::CharToDigit( new_man[ index + conv.comma_digits + 1 ], conv.base );
|
||||
|
||||
// we're cutting the rest of the string
|
||||
new_man.erase(index + max_digit_after_comma + 1, after_comma - max_digit_after_comma);
|
||||
new_man.erase(index + conv.comma_digits + 1, after_comma - conv.comma_digits);
|
||||
|
||||
if( max_digit_after_comma == 0 )
|
||||
if( conv.comma_digits == 0 )
|
||||
{
|
||||
// we're cutting the comma operator as well
|
||||
// (it's not needed now because we've cut the whole rest after the comma)
|
||||
new_man.erase(index, 1);
|
||||
}
|
||||
|
||||
if( last_digit >= base / 2 )
|
||||
if( last_digit >= conv.base / 2 )
|
||||
// we must round here
|
||||
ToString_RoundMantissa_AddOneIntoMantissa(new_man, base, decimal_point);
|
||||
ToString_RoundMantissa_AddOneIntoMantissa<string_type, char_type>(new_man, conv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
a method for converting a string into its value
|
||||
|
||||
it returns 1 if the value is too big -- we cannot pass it into the range
|
||||
of our class Big<exp,man> (or if the base is incorrect)
|
||||
|
||||
that means only digits before the comma operator can make this value too big,
|
||||
all digits after the comma we can ignore
|
||||
|
||||
'source' - pointer to the string for parsing
|
||||
|
||||
if 'after_source' is set that when this method finishes
|
||||
it sets the pointer to the new first character after parsed value
|
||||
|
||||
'value_read' - if the pointer is provided that means the value_read will be true
|
||||
only when a value has been actually read, there can be situation where only such
|
||||
a string '-' or '+' will be parsed -- 'after_source' will be different from 'source' but
|
||||
no value has been read (there are no digits)
|
||||
on other words if 'value_read' is true -- there is at least one digit in the string
|
||||
*/
|
||||
uint FromString(const char * source, uint base = 10, const char ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
Conv conv;
|
||||
conv.base = base;
|
||||
|
||||
return FromStringBase(source, conv, after_source, value_read);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting a string into its value
|
||||
*/
|
||||
uint FromString(const wchar_t * source, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
Conv conv;
|
||||
conv.base = base;
|
||||
|
||||
return FromStringBase(source, conv, after_source, value_read);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting a string into its value
|
||||
*/
|
||||
uint FromString(const char * source, const Conv & conv, const char ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
return FromStringBase(source, conv, after_source, value_read);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting a string into its value
|
||||
*/
|
||||
uint FromString(const wchar_t * source, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
return FromStringBase(source, conv, after_source, value_read);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting a string into its value
|
||||
*/
|
||||
uint FromString(const std::string & string, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
return FromString(string.c_str(), base, after_source, value_read);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting a string into its value
|
||||
*/
|
||||
uint FromString(const std::wstring & string, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
return FromString(string.c_str(), base, after_source, value_read);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting a string into its value
|
||||
*/
|
||||
uint FromString(const std::string & string, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
return FromString(string.c_str(), conv, after_source, value_read);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting a string into its value
|
||||
*/
|
||||
uint FromString(const std::wstring & string, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
return FromString(string.c_str(), conv, after_source, value_read);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
/*!
|
||||
an auxiliary method for converting from a string
|
||||
*/
|
||||
template<class char_type>
|
||||
uint FromStringBase(const char_type * source, uint base = 10, const char_type ** after_source = 0, bool * value_read = 0)
|
||||
uint FromStringBase(const char_type * source, const Conv & conv, const char_type ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
bool is_sign;
|
||||
bool value_read_temp = false;
|
||||
|
||||
if( base<2 || base>16 )
|
||||
if( conv.base<2 || conv.base>16 )
|
||||
{
|
||||
SetNan();
|
||||
|
||||
|
@ -3661,12 +3839,12 @@ private:
|
|||
SetZero();
|
||||
FromString_TestSign( source, is_sign );
|
||||
|
||||
uint c = FromString_ReadPartBeforeComma( source, base, value_read_temp );
|
||||
uint c = FromString_ReadPartBeforeComma( source, conv, value_read_temp );
|
||||
|
||||
if( FromString_TestCommaOperator(source) )
|
||||
c += FromString_ReadPartAfterComma( source, base, value_read_temp );
|
||||
if( FromString_TestCommaOperator(source, conv) )
|
||||
c += FromString_ReadPartAfterComma( source, conv, value_read_temp );
|
||||
|
||||
if( value_read_temp && base == 10 )
|
||||
if( value_read_temp && conv.base == 10 )
|
||||
c += FromString_ReadScientificIfExists( source );
|
||||
|
||||
if( is_sign && !IsZero() )
|
||||
|
@ -3682,48 +3860,6 @@ private:
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
a method for converting a string into its value
|
||||
|
||||
it returns 1 if the value will be too big -- we cannot pass it into the range
|
||||
of our class Big<exp,man> (or if the base is incorrect)
|
||||
|
||||
that means only digits before the comma operator can make this value too big,
|
||||
all digits after the comma we can ignore
|
||||
|
||||
'source' - pointer to the string for parsing
|
||||
'const char*' or 'const wchar_t*'
|
||||
|
||||
if 'after_source' is set that when this method finishes
|
||||
it sets the pointer to the new first character after parsed value
|
||||
|
||||
'value_read' - if the pointer is provided that means the value_read will be true
|
||||
only when a value has been actually read, there can be situation where only such
|
||||
a string '-' or '+' will be parsed -- 'after_source' will be different from 'source' but
|
||||
no value has been read (there are no digits)
|
||||
on other words if 'value_read' is true -- there is at least one digit in the string
|
||||
*/
|
||||
uint FromString(const char * source, uint base = 10, const char ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
return FromStringBase(source, base, after_source, value_read);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting a string into its value
|
||||
*/
|
||||
uint FromString(const wchar_t * source, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
return FromStringBase(source, base, after_source, value_read);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/*!
|
||||
we're testing whether the value is with the sign
|
||||
|
||||
|
@ -3753,10 +3889,10 @@ private:
|
|||
we're testing whether there's a comma operator
|
||||
*/
|
||||
template<class char_type>
|
||||
bool FromString_TestCommaOperator(const char_type * & source)
|
||||
bool FromString_TestCommaOperator(const char_type * & source, const Conv & conv)
|
||||
{
|
||||
if( (*source == TTMATH_COMMA_CHARACTER_1) ||
|
||||
(*source == TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0 ) )
|
||||
if( (*source == static_cast<char_type>(conv.comma)) ||
|
||||
(*source == static_cast<char_type>(conv.comma2) && conv.comma2 != 0 ) )
|
||||
{
|
||||
++source;
|
||||
|
||||
|
@ -3772,18 +3908,25 @@ private:
|
|||
(before the comma operator)
|
||||
*/
|
||||
template<class char_type>
|
||||
uint FromString_ReadPartBeforeComma( const char_type * & source, uint base, bool & value_read )
|
||||
uint FromString_ReadPartBeforeComma( const char_type * & source, const Conv & conv, bool & value_read )
|
||||
{
|
||||
sint character;
|
||||
Big<exp, man> temp;
|
||||
Big<exp, man> base_( base );
|
||||
Big<exp, man> base_( conv.base );
|
||||
|
||||
Misc::SkipWhiteCharacters( source );
|
||||
|
||||
for( ; (character=Misc::CharToDigit(*source, base)) != -1 ; ++source )
|
||||
for( ; true ; ++source )
|
||||
{
|
||||
value_read = true;
|
||||
if( conv.group!=0 && *source==static_cast<char>(conv.group) )
|
||||
continue;
|
||||
|
||||
character = Misc::CharToDigit(*source, conv.base);
|
||||
|
||||
if( character == -1 )
|
||||
break;
|
||||
|
||||
value_read = true;
|
||||
temp = character;
|
||||
|
||||
if( Mul(base_) )
|
||||
|
@ -3802,11 +3945,11 @@ private:
|
|||
(after the comma operator)
|
||||
*/
|
||||
template<class char_type>
|
||||
uint FromString_ReadPartAfterComma( const char_type * & source, uint base, bool & value_read )
|
||||
uint FromString_ReadPartAfterComma( const char_type * & source, const Conv & conv, bool & value_read )
|
||||
{
|
||||
sint character;
|
||||
uint c = 0, index = 1;
|
||||
Big<exp, man> part, power, old_value, base_( base );
|
||||
Big<exp, man> part, power, old_value, base_( conv.base );
|
||||
|
||||
// we don't remove any white characters here
|
||||
|
||||
|
@ -3816,8 +3959,16 @@ private:
|
|||
|
||||
power.SetOne();
|
||||
|
||||
for( ; (character=Misc::CharToDigit(*source, base)) != -1 ; ++source, ++index )
|
||||
for( ; true ; ++source, ++index )
|
||||
{
|
||||
if( conv.group!=0 && *source==static_cast<char>(conv.group) )
|
||||
continue;
|
||||
|
||||
character = Misc::CharToDigit(*source, conv.base);
|
||||
|
||||
if( character == -1 )
|
||||
break;
|
||||
|
||||
value_read = true;
|
||||
|
||||
part = character;
|
||||
|
@ -3849,7 +4000,7 @@ private:
|
|||
// we could break the parsing somewhere in the middle of the string,
|
||||
// but the result (value) still can be good
|
||||
// we should set a correct value of 'source' now
|
||||
for( ; Misc::CharToDigit(*source, base) != -1 ; ++source );
|
||||
for( ; Misc::CharToDigit(*source, conv.base) != -1 ; ++source );
|
||||
|
||||
return (c==0)? 0 : 1;
|
||||
}
|
||||
|
@ -3963,24 +4114,6 @@ private:
|
|||
public:
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting a string into its value
|
||||
*/
|
||||
uint FromString(const std::string & string, uint base = 10)
|
||||
{
|
||||
return FromString( string.c_str(), base );
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting a string into its value
|
||||
*/
|
||||
uint FromString(const std::wstring & string, uint base = 10)
|
||||
{
|
||||
return FromString( string.c_str(), base );
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a constructor for converting a string into this class
|
||||
*/
|
||||
|
@ -4564,8 +4697,7 @@ private:
|
|||
// we're reading only digits (base=10) and only one comma operator
|
||||
for( ; s.good() ; z=static_cast<char_type>(s.get()) )
|
||||
{
|
||||
if( z == TTMATH_COMMA_CHARACTER_1 ||
|
||||
( z == TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0 ) )
|
||||
if( z=='.' || z==',' )
|
||||
{
|
||||
if( was_comma || was_e )
|
||||
// second comma operator or comma operator after 'e' character
|
||||
|
|
|
@ -110,8 +110,7 @@ namespace ttmath
|
|||
for example a correct input string can be:
|
||||
"1"
|
||||
"2.1234"
|
||||
"2,1234" (they are the same, we can either use a comma or a dot in values)
|
||||
(look at the macro TTMATH_COMMA_CHARACTER_2)
|
||||
"2,1234" (they are the same, by default we can either use a comma or a dot)
|
||||
"1 + 2"
|
||||
"(1 + 2) * 3"
|
||||
"pi"
|
||||
|
@ -438,6 +437,28 @@ CGamma<ValueType> cgamma;
|
|||
std::string wide_to_ansi;
|
||||
|
||||
|
||||
/*!
|
||||
group character (used when parsing)
|
||||
default zero (not used)
|
||||
*/
|
||||
int group;
|
||||
|
||||
|
||||
/*!
|
||||
characters used as a comma
|
||||
default: '.' and ','
|
||||
comma2 can be zero (it means it is not used)
|
||||
*/
|
||||
int comma, comma2;
|
||||
|
||||
|
||||
/*!
|
||||
an additional character used as a separator between function parameters
|
||||
(semicolon is used always)
|
||||
*/
|
||||
int param_sep;
|
||||
|
||||
|
||||
/*!
|
||||
true if something was calculated (at least one mathematical operator was used or a function or a variable)
|
||||
*/
|
||||
|
@ -1713,9 +1734,15 @@ void ReadValue(Item & result, int reading_base)
|
|||
{
|
||||
const char * new_stack_pointer;
|
||||
bool value_read;
|
||||
Conv conv;
|
||||
|
||||
uint carry = result.value.FromString(pstring, reading_base, &new_stack_pointer, &value_read);
|
||||
pstring = new_stack_pointer;
|
||||
conv.base = base;
|
||||
conv.comma = comma;
|
||||
conv.comma2 = comma2;
|
||||
conv.group = group;
|
||||
|
||||
uint carry = result.value.FromString(pstring, conv, &new_stack_pointer, &value_read);
|
||||
pstring = new_stack_pointer;
|
||||
|
||||
if( carry )
|
||||
Error( err_overflow );
|
||||
|
@ -1730,10 +1757,10 @@ bool value_read;
|
|||
*/
|
||||
bool ValueStarts(int character, int base)
|
||||
{
|
||||
if( character == TTMATH_COMMA_CHARACTER_1 )
|
||||
if( character == comma )
|
||||
return true;
|
||||
|
||||
if( TTMATH_COMMA_CHARACTER_2 != 0 && character == TTMATH_COMMA_CHARACTER_2 )
|
||||
if( comma2!=0 && character==comma2 )
|
||||
return true;
|
||||
|
||||
if( Misc::CharToDigit(character, base) != -1 )
|
||||
|
@ -1989,7 +2016,7 @@ int ReadOperator(Item & result)
|
|||
++pstring;
|
||||
}
|
||||
else
|
||||
if( *pstring == ';' )
|
||||
if( *pstring == ';' || (param_sep!=0 && *pstring==param_sep) )
|
||||
{
|
||||
result.type = Item::semicolon;
|
||||
++pstring;
|
||||
|
@ -2464,12 +2491,16 @@ public:
|
|||
Parser(): default_stack_size(100)
|
||||
{
|
||||
pstop_calculating = 0;
|
||||
puser_variables = 0;
|
||||
puser_functions = 0;
|
||||
puser_variables = 0;
|
||||
puser_functions = 0;
|
||||
pfunction_local_variables = 0;
|
||||
base = 10;
|
||||
deg_rad_grad = 1;
|
||||
error = err_ok;
|
||||
base = 10;
|
||||
deg_rad_grad = 1;
|
||||
error = err_ok;
|
||||
group = 0;
|
||||
comma = '.';
|
||||
comma2 = ',';
|
||||
param_sep = 0;
|
||||
|
||||
CreateFunctionsTable();
|
||||
CreateVariablesTable();
|
||||
|
@ -2488,7 +2519,11 @@ Parser<ValueType> & operator=(const Parser<ValueType> & p)
|
|||
pfunction_local_variables = 0;
|
||||
base = p.base;
|
||||
deg_rad_grad = p.deg_rad_grad;
|
||||
error = err_ok;
|
||||
error = p.error;
|
||||
group = p.group;
|
||||
comma = p.comma;
|
||||
comma2 = p.comma2;
|
||||
param_sep = p.param_sep;
|
||||
|
||||
/*
|
||||
we don't have to call 'CreateFunctionsTable()' etc.
|
||||
|
@ -2516,6 +2551,7 @@ Parser(const Parser<ValueType> & p): default_stack_size(p.default_stack_size)
|
|||
|
||||
/*!
|
||||
the new base of mathematic system
|
||||
default is 10
|
||||
*/
|
||||
void SetBase(int b)
|
||||
{
|
||||
|
@ -2570,6 +2606,39 @@ void SetFunctions(const Objects * pf)
|
|||
}
|
||||
|
||||
|
||||
/*!
|
||||
setting the group character
|
||||
default zero (not used)
|
||||
*/
|
||||
void SetGroup(int g)
|
||||
{
|
||||
group = g;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
setting the main comma operator and the additional comma operator
|
||||
the additional operator can be zero (which means it is not used)
|
||||
default are: '.' and ','
|
||||
*/
|
||||
void SetComma(int c, int c2 = 0)
|
||||
{
|
||||
comma = c;
|
||||
comma2 = c2;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
setting an additional character which is used as a parameters separator
|
||||
the main parameters separator is a semicolon (is used always)
|
||||
|
||||
this character is used also as a global separator
|
||||
*/
|
||||
void SetParamSep(int s)
|
||||
{
|
||||
param_sep = s;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
the main method using for parsing string
|
||||
|
|
|
@ -233,23 +233,6 @@ namespace ttmath
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/*!
|
||||
characters which represent the comma operator
|
||||
|
||||
TTMATH_COMMA_CHARACTER_1 is used in reading (parsing) and in writing (default, can be overwritten in ToString() function)
|
||||
TTMATH_COMMA_CHARACTER_2 can be used in reading as an auxiliary comma character
|
||||
that means you can input values for example 1.2345 and 1,2345 as well
|
||||
|
||||
if you don't want it just put 0 there e.g.
|
||||
#define TTMATH_COMMA_CHARACTER_2 0
|
||||
then only TTMATH_COMMA_CHARACTER_1 will be used
|
||||
|
||||
don't put there any special character which is used by the parser
|
||||
(for example a semicolon ';' shouldn't be there)
|
||||
*/
|
||||
#define TTMATH_COMMA_CHARACTER_1 '.'
|
||||
#define TTMATH_COMMA_CHARACTER_2 ','
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
|
@ -336,6 +319,114 @@ namespace ttmath
|
|||
};
|
||||
|
||||
|
||||
/*!
|
||||
this struct is used when converting to/from a string
|
||||
*/
|
||||
struct Conv
|
||||
{
|
||||
/*!
|
||||
base (radix) on which the value will be shown (or read)
|
||||
default: 10
|
||||
*/
|
||||
uint base;
|
||||
|
||||
|
||||
/*!
|
||||
used only in Big::ToString()
|
||||
if true the value will be always shown in the scientific mode, e.g: 123e+30
|
||||
default: false
|
||||
*/
|
||||
bool scient;
|
||||
|
||||
|
||||
/*!
|
||||
used only in Big::ToString()
|
||||
if scient is false then the value will be print in the scientific mode
|
||||
only if the exponent is greater than scien_from
|
||||
default: 15
|
||||
*/
|
||||
sint scient_from;
|
||||
|
||||
|
||||
/*!
|
||||
used only in Big::ToString()
|
||||
tells how many digits after comma are possible
|
||||
default: -1 which means all digits are printed
|
||||
|
||||
set it to zero if you want integer value only
|
||||
|
||||
for example when the value is:
|
||||
12.345678 and comma_digit is 4
|
||||
then the result will be
|
||||
12.3457 (the last digit was rounded)
|
||||
*/
|
||||
sint comma_digits;
|
||||
|
||||
|
||||
/*!
|
||||
if true that not mattered digits in the mantissa will be cut off
|
||||
(zero characters at the end -- after the comma operator)
|
||||
e.g. 1234,78000 will be: 1234,78
|
||||
default: true
|
||||
*/
|
||||
bool trim_zeroes;
|
||||
|
||||
|
||||
/*!
|
||||
the main comma operator (used when reading and writing)
|
||||
default is a dot '.'
|
||||
*/
|
||||
uint comma;
|
||||
|
||||
|
||||
/*!
|
||||
additional comma operator (used only when reading)
|
||||
if you don't want it just set it to zero
|
||||
default is a comma ','
|
||||
|
||||
this allowes you to convert from a value:
|
||||
123.45 as well as from 123,45
|
||||
*/
|
||||
uint comma2;
|
||||
|
||||
|
||||
/*!
|
||||
it sets the character which is used for grouping
|
||||
if group=' ' then: 1234,56789 will be printed as: 1 234,567 89
|
||||
|
||||
if you don't want grouping just set it to zero (which is default)
|
||||
*/
|
||||
uint group;
|
||||
|
||||
|
||||
/*!
|
||||
*/
|
||||
uint group_exp; // not implemented yet
|
||||
|
||||
|
||||
/*!
|
||||
*/
|
||||
bool group_multiple; // not implemented yet
|
||||
|
||||
|
||||
Conv()
|
||||
{
|
||||
// default values
|
||||
base = 10;
|
||||
scient = false;
|
||||
scient_from = 15;
|
||||
comma_digits = -1; // !! change to 'round' ?
|
||||
trim_zeroes = true;
|
||||
comma = '.';
|
||||
comma2 = ',';
|
||||
group = 0;
|
||||
group_exp = 0;
|
||||
group_multiple = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this simple class can be used in multithreading model
|
||||
(you can write your own class derived from this one)
|
||||
|
|
Loading…
Reference in New Issue