Author: tkreuzer
Date: Mon Jan 3 19:39:17 2011
New Revision: 50278
URL:
http://svn.reactos.org/svn/reactos?rev=50278&view=rev
Log:
[CRT]
Fix a number of errors in floating point output.
Modified:
trunk/reactos/lib/sdk/crt/printf/streamout.c
Modified: trunk/reactos/lib/sdk/crt/printf/streamout.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/sdk/crt/printf/streamo…
==============================================================================
--- trunk/reactos/lib/sdk/crt/printf/streamout.c [iso-8859-1] (original)
+++ trunk/reactos/lib/sdk/crt/printf/streamout.c [iso-8859-1] Mon Jan 3 19:39:17 2011
@@ -71,7 +71,7 @@
# 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 @@
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 @@
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 @@
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 @@
{
(*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 @@
/* Digits before the decimal point */
do
{
- *--(*string) = digits[val64 % base];
- val64 /= base;
- }
- while (val64);
+ *--(*string) = digits[(unsigned __int64)fpval2 % base];
+ fpval2 /= base;
+ }
+ while ((unsigned __int64)fpval2);
}