Date: Fri, 15 Aug 2003 10:10:45 +0300 (EET DST) From: Esa A E Peuha 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: References: <46 DOT 3c4de930 DOT 2c6a2e90 AT aol DOT com> <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 Content-Type: TEXT/PLAIN; charset=US-ASCII 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 Precedence: bulk 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/