Mail Archives: djgpp-workers/2003/08/11/13:56:31
> Date: Mon, 11 Aug 2003 09:28:05 -0400
> From: DJ Delorie <dj AT delorie DOT com>
>
> > Since _doprnt does some amount of math on its argument, loss of
> > precision beyond the significant digits is inevitable.
>
> If that's our excuse, it's still a bug. We should choose better
> methods so that we don't lose precision.
Based on a short debugging session, here's what I have:
. The closest long double to (unsigned long long)(-1) is
18446744073709551613.75;
. The following loop inside cvtl produces the digits:
for (; integer && p >= startp; ++expcnt)
{
tmp = modfl(integer * 0.1L , &integer);
*p-- = tochar((int)((tmp + .01L) * 10));
}
. On the first iteration (which produces the last, i.e. rightmost)
digit, tmp is set to 0.375, then (tmp + 0.01) * 10 gives 3.85 and
conversion to int gives 3.
. Thus, tochar yields `3'. This is supposed to be rounded to `4' by
this fragment:
/* if requires more precision and some fraction left */
if (fract)
{
if (prec)
do {
fract = modfl(fract * 10.0L, &tmp);
*t++ = tochar((int)tmp);
} while (--prec && fract);
if (fract)
startp = roundl(fract, (int *)NULL, startp,
t - 1, (char)0, signp);
}
However, fract is zero in this case, so rounding never happens.
Perhaps the problem is in modfl (which produced the value of fract
earlier inside cvtl). Maybe someone could take a closer look at
modfl for such extreme arguments.
- Raw text -