On 2004-Jul-11 21:06:32 +0400, Dmitry Morozovsky <[EMAIL PROTECTED]> wrote:
>[EMAIL PROTECTED]:/tmp/tsostik> cat x.c
>#include <stdio.h>
>int main ()
>{
>        float a;
>        for(a=0.01;a<=0.1; a+=0.01)
>          printf("%f %.3f %d\n", a*100, a*100, (int)(a*100));
>return 0;
>}
>[EMAIL PROTECTED]:/tmp/tsostik> cc x.c
>[EMAIL PROTECTED]:/tmp/tsostik> ./a.out
>1.000000 1.000 0
>2.000000 2.000 1
>3.000000 3.000 2
>4.000000 4.000 3
>5.000000 5.000 5
>6.000000 6.000 6
>7.000000 7.000 7
>8.000000 8.000 7
>9.000000 9.000 8
>9.999999 10.000 9

As various other people have pointed out, this is an artifact of
binary floating point arithmetic, rather than gcc.  Note that
single-precision floating point only gives you 24 binary (or 7.22
decimal) digits of precision.  Expecting to accurately display 7
digits may be somewhat hopeful.

The correct solution is to use rint(3), rather than casting to int
(which is truncation).  ceil(3) will solve this specific issue but
is just as susceptable to unexpected rounding.

Switching to double precision will help but is still not a complete
solution.  I looked into a similar problem this a few years ago
following a complaint that int(0.29 * 100) == 28 in double precision.
The following is my analysis of that problem.

The underlying problem is that 1/100 is not representable in a finite
number of bits. Specifically,
1/100 = 0d0.01 = 0b0.0000[00101000111101011100] = 0x0.0[28F5C]
(where the brackets enclose the repeating digits).

As an example, 0.29 = 0x0.4[A3D70].  Expressed as a rounded IEEE 754
double precision number, this is 0x3fd28f5c28f5c28f, which
underestimates the correct value by ~2e-17 (0.36ULP[1]).  When this
number is multiplied by 100, the underestimate becomes 0.56ULP,
causing the result to round down (ie the result is 1ULP = ~3.4e-15
low).  Since conversion-to-integer is defined to round towards zero,
this gives an integer value of 28.

A good (though not hyper-linked) bibliography on floating point can be
found at http://www.cse.nd.edu/~milind/references/floatingpoint.  Prof
William Kahan's writings (http://www.cs.berkeley.edu/~wkahan/) also make
interesting reading.

[1] Units in the Last Place.

Peter
_______________________________________________
[EMAIL PROTECTED] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to