3

In C, if we execute the following code:

float a = 0.7;
if (a < 0.7)
{
    printf("Less");
}
else
{
    printf("no");
}

The code above code prints "Less".

But if we execute the following code:

float a = 1.7;
if (a < 1.7)
{
    printf("Less");
}
else
{
    printf("no");
} 

It prints "no".

What's the reason for that? How does the float datatype work?

ST3
  • 8,826
  • 3
  • 68
  • 92
deepak
  • 199
  • 2
  • 9
  • 1
    you might want to lookup "floating point rounding errors" - there are huge articles about those issues :-) – Arne Mertz Jul 04 '13 at 17:58
  • 2
    A must read - http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html – Luchian Grigore Jul 04 '13 at 17:58
  • 1
    [As you can see here](https://ideone.com/e8N7pn), it prints less with C++11 as well. Refer to Luchian's links as to why. – Borgleader Jul 04 '13 at 18:00
  • 1
    if you really want to compare floating literals, add F after it like 23.6F. – Saksham Jul 04 '13 at 18:15
  • 1
    like= 100/3 = 33.3333...... similarly when you convert `0.7` in binary you will get a infinite(or long) sequence of `0`,`1` that is the reason four byte `float` `.7f`!= eight byte `double` `0.7`.Just remember unsuffixed floating-point literals are double, and rounding means that even small literals can take on different values when rounded to float and double. – Grijesh Chauhan Jul 04 '13 at 18:25

2 Answers2

11

The problem is that a is a float, but 0.7 is a double. The values assigned into a are converted from double to float, which loses precision. When you compare a back to the double, a is widened to a double, but the precision is already lost, and they may no longer be equal.

If you change 0.7 and 1.7 to 0.7f and 1.7f then they will be converted to float literals and will reliably compare equal to a in both cases.

Peter Alexander
  • 53,344
  • 14
  • 119
  • 168
1

The float datatype works with approximate values. Every numeric data type in C/C++ uses a finite, fixed amount of bytes to store values. float stores values in exponential format in such a way that if you pass a value in another format to it, the value will be rounded... And then, if you look at enough digits past the decimal separator you are sure to see non-zero values. And 1.7, as Peter Alexander said in his answer, is not a "pure" float value.

A further, detailed explanation of the motives behind such a design might be too long for an asnwer here - but you may read more about that if you google for it. One of the commenters, Luchian, left a good link there: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

Geeky Guy
  • 9,229
  • 4
  • 42
  • 62