From 316a3efbaca3bfc42b44e414df99f3ab84079a22 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Mon, 3 Jan 2011 19:39:17 +0000 Subject: [PATCH] [CRT] Fix a number of errors in floating point output. svn path=/trunk/; revision=50278 --- reactos/lib/sdk/crt/printf/streamout.c | 58 +++++++++++++++----------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/reactos/lib/sdk/crt/printf/streamout.c b/reactos/lib/sdk/crt/printf/streamout.c index 846ae45e9ed..7db71691b96 100644 --- a/reactos/lib/sdk/crt/printf/streamout.c +++ b/reactos/lib/sdk/crt/printf/streamout.c @@ -71,7 +71,7 @@ enum # define _flsbuf(chr, stream) 0 #endif -#define get_exp(f) floor(f > 0 ? log10(f) : log10(-f)) +#define get_exp(f) floor(f == 0 ? 0 : (f >= 0 ? log10(f) : log10(-f))) void #ifdef _LIBCNT @@ -92,16 +92,30 @@ format_float( static const TCHAR _nan[] = _T("#QNAN"); static const TCHAR _infinity[] = _T("#INF"); const TCHAR *digits = digits_l; - int exponent = 0; - long double fpval; - int num_digits, val32, base = 10; - __int64 val64; + int exponent = 0, sign; + long double fpval, fpval2; + int padding = 0, num_digits, val32, base = 10; + /* Normalize the precision */ if (precision < 0) precision = 6; - else if (precision > 512) precision = 512; + else if (precision > 17) + { + padding = precision - 17; + precision = 17; + } + /* Get the float value and calculate the exponent */ fpval = va_arg_ffp(*argptr, flags); exponent = get_exp(fpval); + sign = fpval < 0 ? -1 : 1; + + /* Shift the decimal point and round */ + fpval2 = round(sign * fpval * pow(10., precision - exponent)); + if (fpval2 >= (unsigned __int64)pow(10., precision + 1)) + { + exponent++; + fpval2 = round(sign * fpval * pow(10., precision - exponent)); + } switch (chr) { @@ -111,21 +125,18 @@ format_float( if (precision > 0) precision--; if (exponent < -4 || exponent >= precision) goto case_e; - /* Skip trailing 0s */ - val64 = (__int64)(fpval * pow(10., precision) + 0.5); - while (precision && val64 % 10 == 0) + /* Skip trailing zeroes */ + while (precision && (unsigned __int64)fpval2 % 10 == 0) { precision--; - val64 /= 10; + fpval2 /= 10; } - break; case _T('E'): digits = digits_u; case _T('e'): case_e: - fpval /= pow(10., exponent); val32 = exponent >= 0 ? exponent : -exponent; // FIXME: handle length of exponent field: @@ -154,13 +165,9 @@ format_float( break; } - /* CHECKME: Windows seems to handle a max of 17 digits(?) */ - num_digits = precision <= 17 ? precision: 17; - /* Handle sign */ if (fpval < 0) { - fpval = -fpval; *prefix = _T("-"); } else if (flags & FLAG_FORCE_SIGN) @@ -173,22 +180,25 @@ format_float( { (*string) -= sizeof(_nan) / sizeof(TCHAR) - 1; _tcscpy((*string), _nan); - val64 = 1; + fpval2 = 1; } else if (!_finite(fpval)) { (*string) -= sizeof(_infinity) / sizeof(TCHAR) - 1; _tcscpy((*string), _infinity); - val64 = 1; + fpval2 = 1; } else { + /* Zero padding */ + while (padding-- > 0) *--(*string) = _T('0'); + /* Digits after the decimal point */ - val64 = (__int64)(fpval * pow(10., precision) + 0.5); + num_digits = precision; while (num_digits-- > 0) { - *--(*string) = digits[val64 % 10]; - val64 /= 10; + *--(*string) = digits[(unsigned __int64)fpval2 % 10]; + fpval2 /= base; } } @@ -198,10 +208,10 @@ format_float( /* Digits before the decimal point */ do { - *--(*string) = digits[val64 % base]; - val64 /= base; + *--(*string) = digits[(unsigned __int64)fpval2 % base]; + fpval2 /= base; } - while (val64); + while ((unsigned __int64)fpval2); } -- 2.17.1