www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2003/08/15/03:15:18

Date: Fri, 15 Aug 2003 10:10:45 +0300 (EET DST)
From: Esa A E Peuha <peuha AT cc DOT helsinki DOT fi>
Sender: peuha AT sirppi DOT helsinki DOT fi
To: djgpp-workers AT delorie DOT com
Subject: Re: Anomaly in printf()
In-Reply-To: <7458-Thu14Aug2003112749+0300-eliz@elta.co.il>
Message-ID: <Pine.OSF.4.51.0308151000100.13877@sirppi.helsinki.fi>
References: <46 DOT 3c4de930 DOT 2c6a2e90 AT aol DOT com> <Pine DOT OSF DOT 4 DOT 51 DOT 0308131046310 DOT 2694 AT sirppi DOT helsinki DOT fi>
<3F3B2D8E DOT F90E84B5 AT phekda DOT freeserve DOT co DOT uk> <7458-Thu14Aug2003112749+0300-eliz AT elta DOT co DOT il>
MIME-Version: 1.0
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

On Thu, 14 Aug 2003, Eli Zaretskii wrote:

> As I'd expect, FWIW: the problem seems to be that the result of either
> multiplying by 0.1 or dividing by 10 does not have an exact FP
> representation.  That is, we are seeing inaccuracies in the last
> significant digit which are to be expected.
>
> I don't know how to fix this without a radical change in the
> algorithm.

I do. :-)  This is really a classic case of the wrong way to compute
remainder modulo something; this patch does it the right way:

Index: doprnt.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/ansi/stdio/doprnt.c,v
retrieving revision 1.16
diff -c -p -r1.16 doprnt.c
*** doprnt.c	30 Jun 2003 20:38:15 -0000	1.16
--- doprnt.c	15 Aug 2003 06:59:23 -0000
*************** cvtl(long double number, int prec, int f
*** 579,594 ****
          else doextradps=1;
    }
    /*
!    * get integer portion of number; put into the end of the buffer; the
!    * .01 is added for modf(356.0 / 10, &integer) returning .59999999...
     * The test p >= startp is due to paranoia: buffer length is guaranteed
     * to be large enough, but if tmp is somehow a NaN, this loop could
     * eventually blow away the stack.
     */
    for (; integer && p >= startp; ++expcnt)
    {
!     tmp = modfl(integer * 0.1L , &integer);
!     *p-- = tochar((int)((tmp + .01L) * 10));
    }
    switch(fmtch)
    {
--- 579,594 ----
          else doextradps=1;
    }
    /*
!    * get integer portion of number; put into the end of the buffer.
     * The test p >= startp is due to paranoia: buffer length is guaranteed
     * to be large enough, but if tmp is somehow a NaN, this loop could
     * eventually blow away the stack.
     */
    for (; integer && p >= startp; ++expcnt)
    {
!     modfl(integer / 10.0L , &tmp);
!     *p-- = tochar((int)(integer - (tmp * 10.0L)));
!     integer = tmp;
    }
    switch(fmtch)
    {

-- 
Esa Peuha
student of mathematics at the University of Helsinki
http://www.helsinki.fi/~peuha/

- Raw text -


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