1

Comparing Same Float Values In C

strange output in comparison of float with float literal

Float addition promoted to double?


I read the above links on floating points, but even getting strange output.

#include<stdio.h>
int main()
{
    float x = 0.5;

    if (x == 0.5)
        printf("IF");

    else if (x == 0.5f)
        printf("ELSE IF");

    else
        printf("ELSE");
}

Now, according to the promotion rules, Shouldn't "ELSE IF" must be printed ?

But, here it is printing "IF"


EDIT : Is it because 0.5 = 0.1 in binary and everything is 0 after that and loss of precision hence no effects, so comparison IF returns true.

Had it been 0.1, 0.2, 0.3, 0.4, 0.6, 0.7.... , then Else If block returns true.


Pardon me asking same question, because I have read from the above links that floats comparison must never be done.

But, What is the reason of this unexpected behaviour ?

Community
  • 1
  • 1
  • [The usual arithmetic conversion rules](http://en.cppreference.com/w/c/language/conversion#Usual_arithmetic_conversions) states that if one of the operands is a `double` then the other operand is converted to a `double`. So the condition `x == 0.5` is actually `(double) x == 0.5` which of course is true. However, due to the problems with floating point values on computers (see e.g. [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) for details), there are very few values for which this is true. – Some programmer dude Jan 17 '17 at 07:33
  • I still think it's a little unclear exactly what you're asking, but if I understand it correctly (and go with the answer provided by Gerhardh) then yes you're right. – Some programmer dude Jan 17 '17 at 07:41
  • @Someprogrammerdude Yes, That's exactly what I infer. Thanks !! –  Jan 17 '17 at 07:42
  • 3
    *"They are never accurate."* This is common misconception. Floats are as accurate as integers for values they were designed to be representing. It's just that programmers often have wrong expectations and various type conversion rules of C are not helping. – user694733 Jan 17 '17 at 07:47

3 Answers3

5

As you have read the links regarding problems with floating point types and comparisons, you are probably expecting that 0.5 is rounded during conversion and hence the comparison should fail. But 0.5 is a power of 2 and can be represented perfectly without any rounding in a float or double type variable. Therefore the comparison results in TRUE.

After your edited your question: Yes, if you took 0.1 or one of the other values you mention, you should run into the else part.

Gerhardh
  • 11,688
  • 4
  • 17
  • 39
5

Floating point numbers are never accurate.

This statement is wrong. Some floating point numbers are accurate, such as 1.0, 12345.0, 12345.5, -2.25. All these numbers can be represented as integers didived by a power of 2. All numbers that cannot also are not accurate.

In your specific case, float x = 0.5 results in x having the value 1.00000000 * 2^-1. When you compare this against double 0.5, both operands are converted to double, so the comparison becomes 1.000000000000000 * 2^-1 == 1.000000000000000 * 2^-1, which succeeds.

For float x = 0.1, it looks different. The value is stored as 1.01010101 * 2^-3 (or similar). Note that this is already not precise. When you compare this against double 0.1, the float is extended with zeros at the end, the comparison becomes 1.010101010000000 * 2^-3 == 1.010101010101010 * 2^-3, which fails.

Roland Illig
  • 40,703
  • 10
  • 88
  • 121
  • Thanks !! Got what I was looking for !! But, I can't upvote it . –  Jan 17 '17 at 08:14
  • 3
    I would actually say that all floating point numbers are accurate. It's expressing them in decimal notation that isn't accurate. The problem isn't the numbers, the problem is converting them to/from decimal strings. If we only expressed integers as fractions of 3 they'd be "inaccurate" too. – Art Jan 17 '17 at 10:14
-1

The first if statement evaluates to true, so IF is printed. The other expressions aren't even checked.

Scovetta
  • 3,112
  • 1
  • 14
  • 13