newlib printf %f BUG

Ted Merrill
Mon Jan 15 17:58:00 GMT 2001

I hope this is where to report bugs.

Using both newlib-1.8.2 and newlib-1.9.0 compiled using gcc for ARM/thumb
architecture using gcc 3.0, 
a bug in printf floating point formatting is seen for some numbers.

Sample code:

void MathTest2(void)
    /* This tests a bug we found in newlib 1.8.2
    double R = 3.4263125;
    printf("%.6f\n", R );

R is printed as:   4.5373:7
which is not at all the right answer.
NOTE the colon; this is the ascii character following '9'
which should give some clue.

The correct answer is 3.426312 or perhaps maybe 3.426313; 
we are at the rounding boundary
when rounding to 6 digits after decimal place.
Apparently the rounding goes haywire?

Info from gcc -v :
Reading specs from /s/wdsl/i/bin.sun5/arm.gcc/specs
Configured with: /s/home/ted/tool.1/i/include/gcc-3.0-acom.1/configure --host=sparc-sun-solaris2.5.1 --prefix=/s/home/ted/_tool/_gccarm/junk.i/sun5-arm --srcdir=/s/home/ted/tool.1/i/include/gcc-3.0-acom.1 --target=arm-ecos-elf --enable-languages=c --with-headers=/s/home/ted/_tool/_gccarm/oo/include/arm.usr.include --with-libs=/s/home/ted/_tool/_gccarm/oo/lib.arm/arm.usr.lib
Thread model: single
gcc version 3.0

Has this bug been spotted by someone else? Any fix?

- Ted Merrill, ArrayComm, Inc.


I'm attempt to find (and fix) the problem in the newlib source code.
Things go well until line 517 of stdlib/dtoa.c
where the following code appears:

                  if (d.d > 0.5 + eps.d)
                    goto bump_up;
                  else if (d.d < 0.5 - eps.d)
                      while (*--s == '0');
                      goto ret1;

d.d at this point is .499999...something and doesn't fall into either
camp... so it falls through to a label "fast_failed" and from there
rapidly down to line 811 where I confess i lose what the algorithm
is trying to do... although clearly at this point it is generating the
wrong answer that i see printed.

Not being too concerned with having exactly the right rounding, i've
simply changed the code above to:
                  // LESS PRECISE BUT WORKING CODE
                  if (d.d >= 0.5 ) 
                    goto bump_up;
                      while (*--s == '0');
                      goto ret1;

More information about the Newlib mailing list