-2

I have come across two programs in C, both comparing floating point number but with different outputs.

1)

  #include<stdio.h>
   int main()
   {
       float x = 0.1;
       if (x == 0.1)
           printf("IF");
       else if (x == 0.1f)
            printf("ELSE IF");
       else
            printf("ELSE");
    }

Output : ELSE IF

2)

    int main()
   {
       float x = 0.5;
       if (x == 0.5)
           printf("IF");
       else if (x == 0.5f)
            printf("ELSE IF");
       else
            printf("ELSE");
    }

Output : IF

why 0.5 is not promoted to double whereas 0.1 is?

  • 2
    Possible duplicate of [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken), http://stackoverflow.com/questions/2386772/difference-between-float-and-double, http://stackoverflow.com/questions/10334688/how-dangerous-is-it-to-compare-floating-point-values, http://stackoverflow.com/questions/35141663/c-float-and-double-comparisons, http://stackoverflow.com/questions/29962813/why-floating-point-comparisons-gives-different-outputs-on-different-compiler – Cody Gray - on strike May 07 '17 at 10:15

2 Answers2

4

Since double is wider than float, x == 0.1 is interpreted as (double) x == 0.1.

This works for 0.5 because 0.5 is exactly representable in binary, so (double) 0.5f produces precisely 0.5. On the other hand, 0.1 has an infinite-digit representation in binary, and 0.1f and 0.1 end up being rounded to numbers that differ in how many initial digits of the sequence they hold.

In an analogy with decimal numbers, you can think of the above situation as trying to write down the fraction 1/3 by rounding it to a fixed number of decimal digits. Using a 5-significant-digit representation, you get 0.33333; choosing a 10-digit one results in 0.3333333333. Now, "casting" the five-digit number to ten digits results in 0.3333300000, which is a different number than 0.3333333333. In the same analogy, 0.5 in is like 1/10 in decimal, which would be represented as 0.10000 and 0.1000000000 respectively, so one could convert it to the other representation and back without changing its meaning.

If the contents of x is a marker value set from code, then simply compare it to 0.1f instead of to 0.1. If it is the result of a calculation, see Paul's answer for the correct way to compare floating-point quantities.

Community
  • 1
  • 1
user4815162342
  • 141,790
  • 18
  • 296
  • 355
0

The proper way of comparing one floating point number with another is by using a precission value, for example

#define EPS 0.00001
#define ABS(a) ((a)<0?-(a):(a))

if (ABS(a-b)<EPS)
    ...

This is derived from:

if (a == b)           // "equal" of fp numbers is not well defined
if (a-b == 0)         // so comparing with zero is also ill defined
if (ABS(a-b) < EPS)   // and so we compare with this small precission
Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41