www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2003/08/11/13:56:31

Date: Mon, 11 Aug 2003 19:45:45 +0200
From: "Eli Zaretskii" <eliz AT elta DOT co DOT il>
Sender: halo1 AT zahav DOT net DOT il
To: djgpp-workers AT delorie DOT com
Message-Id: <9003-Mon11Aug2003194545+0300-eliz@elta.co.il>
X-Mailer: emacs 21.3.50 (via feedmail 8 I) and Blat ver 1.8.9
In-reply-to: <200308111328.h7BDS5un031026@envy.delorie.com> (message from DJ
Delorie on Mon, 11 Aug 2003 09:28:05 -0400)
Subject: Re: Anomaly in printf()
References: <1e0 DOT eca6e87 DOT 2c67e363 AT aol DOT com> <200308101817 DOT h7AIHDhr019129 AT envy DOT delorie DOT com> <9003-Sun10Aug2003222306+0300-eliz AT elta DOT co DOT il> <200308102312 DOT h7ANC6mQ021365 AT envy DOT delorie DOT com> <uu18osptc DOT fsf AT elta DOT co DOT il> <200308111328 DOT h7BDS5un031026 AT envy DOT delorie DOT com>
Reply-To: djgpp-workers AT delorie DOT com
Errors-To: nobody AT delorie DOT com
X-Mailing-List: djgpp-workers AT delorie DOT com
X-Unsubscribes-To: listserv AT delorie DOT com

> 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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019