float variables in loops

Discussion in 'C Programming' started by vijay, May 4, 2005.

  1. vijay

    vijay Guest

    Hello,

    What happens to float variable in loops. For example,

    float f=8.7;
    if(f<8.7)
    printf("less");
    else if(f==8.7)
    printf("equal");
    else if(f>8.7)
    printf("more");

    prints "less". Shouldn't it print "equal".

    regards,
    vijay.
     
    vijay, May 4, 2005
    #1
    1. Advertising

  2. In article <>,
    "vijay" <> wrote:

    > Hello,
    >
    > What happens to float variable in loops. For example,
    >
    > float f=8.7;
    > if(f<8.7)
    > printf("less");
    > else if(f==8.7)
    > printf("equal");
    > else if(f>8.7)
    > printf("more");
    >
    > prints "less". Shouldn't it print "equal".


    No, it shouldn't.

    What is the type of f?
    What is the type of 8.7?
    Are they the same types?
     
    Christian Bau, May 4, 2005
    #2
    1. Advertising

  3. vijay

    -berlin.de Guest

    vijay <> wrote:
    > What happens to float variable in loops. For example,


    > float f=8.7;
    > if(f<8.7)
    > printf("less");
    > else if(f==8.7)
    > printf("equal");
    > else if(f>8.7)
    > printf("more");


    > prints "less". Shouldn't it print "equal".


    No, you can't expect that. The basic problem is that numbers are
    stored with a finite number of digits. And numbers like 8.7 are
    no simple looking numbers anymore when converted to binary but
    have an infinite number of digits (like one third is an infinite
    fraction when written in base 10). But since you only have a
    finite numbers of bits to store them in, the numbers get truncated.
    So most floating point numbers can be stored only as an approxi-
    mation and what's stored of your 8.7 is probably something like
    8.6999998 instead of 8.7 - you can easily see that effect when
    you try to print it out with enough digits, try e.g.

    printf( "%20.18f\n", f );

    Moreover, since (usually) floats have less bits than doubles,
    the same number stored in a float and a double variable will
    differ - just try it out with

    printf( "%20.18f %20.18f\n", f, 8.7 );

    This also indicates that "8.7" isn't treated as a float but
    as a double - all calculations in C are done per default in
    double and all constants like "8.7" are treated as doubles -
    to avoid that you would have to write "8.7f" instead. So what
    you do in your program is comparing the value of the float
    variable 'f' with the value of 8.7 when stored as a double.
    But since these values typically differ you hardly ever will
    get "less" printed out (except for numbers that can be stored
    using a small number of digits, your result would be different
    if you would use e.g. 2.5 instead of 8.7).

    So the first thing to keep in mind when dealing with floating
    point numbers is that comparing them for equaliy will typically
    only work by accident.
    Regards, Jens
    --
    \ Jens Thoms Toerring ___ -berlin.de
    \__________________________ http://www.toerring.de
     
    -berlin.de, May 4, 2005
    #3
  4. vijay wrote:
    > Hello,
    >
    > What happens to float variable in loops. For example,
    >
    > float f=8.7;
    > if(f<8.7)
    > printf("less");
    > else if(f==8.7)
    > printf("equal");
    > else if(f>8.7)
    > printf("more");
    >
    > prints "less". Shouldn't it print "equal".
    >
    > regards,
    > vijay.
    >


    FAQs already address this issue.

    Please read followings ..

    http://www.eskimo.com/~scs/C-faq/q14.4.html
    http://www.eskimo.com/~scs/C-faq/q14.5.html


    Krishanu
     
    Krishanu Debnath, May 4, 2005
    #4
  5. vijay

    vijay Guest

    -berlin.de wrote:
    > vijay <> wrote:
    > > What happens to float variable in loops. For example,

    >
    > > float f=8.7;
    > > if(f<8.7)
    > > printf("less");
    > > else if(f==8.7)
    > > printf("equal");
    > > else if(f>8.7)
    > > printf("more");

    >
    > > prints "less". Shouldn't it print "equal".

    >
    > No, you can't expect that. The basic problem is that numbers are
    > stored with a finite number of digits. And numbers like 8.7 are
    > no simple looking numbers anymore when converted to binary but
    > have an infinite number of digits (like one third is an infinite
    > fraction when written in base 10). But since you only have a
    > finite numbers of bits to store them in, the numbers get truncated.
    > So most floating point numbers can be stored only as an approxi-
    > mation and what's stored of your 8.7 is probably something like
    > 8.6999998 instead of 8.7 - you can easily see that effect when
    > you try to print it out with enough digits, try e.g.
    >
    > printf( "%20.18f\n", f );
    >
    > Moreover, since (usually) floats have less bits than doubles,
    > the same number stored in a float and a double variable will
    > differ - just try it out with
    >
    > printf( "%20.18f %20.18f\n", f, 8.7 );


    8.699999809265136719
    8.699999999999999289

    This is the output I get. How is it really calculated? Does the output
    depend upon the compiler(i'm using gcc), system etc.

    printf( "%20.18f %20.18f\n", f, 8.7f );
    gives the same output, maybe because now it treats 8.7 as a float and
    not as a double.

    regards,
    vijay.
     
    vijay, May 4, 2005
    #5
  6. vijay

    Tim Prince Guest

    "vijay" <> wrote in message
    news:...
    >


    >>
    >> printf( "%20.18f %20.18f\n", f, 8.7 );

    >
    > 8.699999809265136719
    > 8.699999999999999289
    >
    > This is the output I get. How is it really calculated? Does the output
    > depend upon the compiler(i'm using gcc), system etc.

    If your system uses open source libraries, such as glibc or newlib, you have
    the opportunity to look up how printf() et al. do their work. Or, look up
    ideas in a fine reference, such as Plauger's "Standard C Library." On many
    systems, where there is a choice of gcc or other compilers, the same
    printf() would be shared by multiple compilers. A library will comply with
    IEEE standard if it gets 17 digits right, for the standard 64-bit double.
    Accuracy of additional digits may depend on whether your system supports
    long double.
     
    Tim Prince, May 4, 2005
    #6
  7. On Wed, 04 May 2005 08:11:51 +0000, Jens.Toerring wrote:

    ....

    > printf( "%20.18f %20.18f\n", f, 8.7 );
    >
    > This also indicates that "8.7" isn't treated as a float but
    > as a double - all calculations in C are done per default in
    > double


    That was true for K&R C but is not true in standard C where operations
    involving operands of type float or float in combination with
    integer operands produce a float result.

    The default argument promotions, where (amongst other things) a float
    argument gets promoted to double in an unprototyped function call or in a
    variable argument list, still exist in standard C but don't affect
    "calculations".

    Lawrence
     
    Lawrence Kirby, May 4, 2005
    #7
  8. On 4 May 2005 06:24:23 -0700, vijay
    <> wrote:

    > -berlin.de wrote:
    >>
    >> No, you can't expect that. The basic problem is that numbers are
    >> stored with a finite number of digits. And numbers like 8.7 are
    >> no simple looking numbers anymore when converted to binary but
    >> have an infinite number of digits (like one third is an infinite
    >> fraction when written in base 10). But since you only have a
    >> finite numbers of bits to store them in, the numbers get truncated.
    >> So most floating point numbers can be stored only as an approxi-
    >> mation and what's stored of your 8.7 is probably something like
    >> 8.6999998 instead of 8.7 - you can easily see that effect when
    >> you try to print it out with enough digits, try e.g.
    >>
    >> printf( "%20.18f\n", f );
    >>
    >> Moreover, since (usually) floats have less bits than doubles,
    >> the same number stored in a float and a double variable will
    >> differ - just try it out with
    >>
    >> printf( "%20.18f %20.18f\n", f, 8.7 );

    >
    > 8.699999809265136719
    > 8.699999999999999289
    >
    > This is the output I get. How is it really calculated? Does the output
    > depend upon the compiler(i'm using gcc), system etc.


    It depends on the respresentation of float and double on your system,
    which will be related to the compiler and the hardware. The standard
    says only that a float must have at least 6 digits of precision and a
    double at least 10 digits, but they could be identical on some systems
    as long as they meet the minimum criteria.

    > printf( "%20.18f %20.18f\n", f, 8.7f );
    > gives the same output, maybe because now it treats 8.7 as a float and
    > not as a double.


    I assume you mean that both outputs are the same. Yes, if you just say
    8.7 it is interpreted as a double (6.4.4.1 para 4), if you say 8.7f then
    it will be a float.

    In general, however, comparing floating point numbers for exact equality
    is not sensible, because rounding can occur without you knowing it. For
    instance, 9.7 - 8.7 == 1.0 may well fail, as may (x+1) - 1 == x. In
    general the way to test is for "near equality", choose some value
    EPSILON and do something like:

    if (abs(expression) < EPSILON)
    /* near enough */

    or even write it as a function so that it auto-scales epsilon according
    to numbers being compared:

    #include <float.h>
    #include <math.h>

    int float_compare(float a, float b)
    {
    float epsilon = (fabs(a) + fabs(b)) * FLT_EPSILON;
    if (a - b > epsilon) return +1;
    if (b - a > epsilon) return -1;
    return 0;
    }

    Chris C
     
    Chris Croughton, May 4, 2005
    #8
  9. vijay

    Kevin Bracey Guest

    In message <>
    Lawrence Kirby <> wrote:

    > On Wed, 04 May 2005 08:11:51 +0000, Jens.Toerring wrote:
    >
    > ...
    >
    > > printf( "%20.18f %20.18f\n", f, 8.7 );
    > >
    > > This also indicates that "8.7" isn't treated as a float but
    > > as a double - all calculations in C are done per default in
    > > double

    >
    > That was true for K&R C but is not true in standard C where operations
    > involving operands of type float or float in combination with
    > integer operands produce a float result.


    That's a half-truth. Yes, the result has semantic type float, but it's
    allowed to have extra precision. Thus in:

    float f;
    double d = f * f;

    the final result d may have full double precision, or it may just have
    float precision, depending on FLT_EVAL_METHOD. So the traditional
    mode of operation where "all calculations in C are done per default in
    double" is still an implementation option.

    And, even more bizarrely - something I didn't know until recently - even
    constants might have more precision than their type. So

    double d = 8.7F;

    could leave you with full double precision. Bleurgh. The only way to
    guarantee a single-precision constant is:

    float f = 8.7F;
    or
    double d = (float) 8.7F;

    --
    Kevin Bracey, Principal Software Engineer
    Tematic Ltd Tel: +44 (0) 1223 503464
    182-190 Newmarket Road Fax: +44 (0) 1728 727430
    Cambridge, CB5 8HE, United Kingdom WWW: http://www.tematic.com/
     
    Kevin Bracey, May 5, 2005
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Andy
    Replies:
    7
    Views:
    6,332
    Roedy Green
    May 10, 2004
  2. bd
    Replies:
    0
    Views:
    670
  3. k3n3dy
    Replies:
    15
    Views:
    1,021
    dan2online
    Apr 20, 2006
  4. Carsten Fuchs
    Replies:
    45
    Views:
    1,658
    James Kanze
    Oct 8, 2009
  5. Me
    Replies:
    2
    Views:
    267
Loading...

Share This Page