Re: gcc strangeness

From: Peter Jeremy (peter.jeremy_at_alcatel.com.au)
Date: 07/14/04

  • Next message: Yar Tikhiy: "Re: Silent errors when reading CDs"
    Date: Wed, 14 Jul 2004 10:54:44 +1000
    To: Dmitry Morozovsky <marck@rinet.ru>
    
    

    On 2004-Jul-11 21:06:32 +0400, Dmitry Morozovsky <marck@rinet.ru> wrote:
    >marck@woozle:/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;
    >}
    >marck@woozle:/tmp/tsostik> cc x.c
    >marck@woozle:/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
    _______________________________________________
    freebsd-hackers@freebsd.org mailing list
    http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
    To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.org"


  • Next message: Yar Tikhiy: "Re: Silent errors when reading CDs"

    Relevant Pages

    • Re: C floating point
      ... > C supports single precision floating point and double precision ... > that fixed floating point is more accurate than single precision ... int dollar; ...
      (comp.lang.c)
    • Re: Calculate the precision of a floating point number (ie: the number of decimal places)
      ... I did not think you wanted the precision (since with internal floating ... binary floating point). ... string as if you were going to print it out. ...
      (comp.programming)
    • Re: double is integer?
      ... safe thing to do ... floating point computations, you may have a value close to but not ... precision anyway. ... long int i = d; ...
      (microsoft.public.vc.mfc)
    • Re: Problem in Float Arithmetic
      ... precision of an integer of the same number of bits of significance as the mantissa of the ... The problem, for example, is that 'float' has fewer bits than ... 'int', so it only becomes interesting when you start using 'double'. ... Floating point arithmetic on integer values that produces integer values is ...
      (microsoft.public.vc.mfc)
    • Re: Math errors in python
      ... Why would BCD floating point have any less range than ... To get the same range and precision as a 32-bit IEEE, ... binary floating point with about a 50% penalty in storage ...
      (comp.lang.python)