float and double confusion

Heloow every1.....
here's my question

int main()
{
float x=0.1;

if(x==0.1)
cout<< "True";
else
cout<< "False";

}


what is the output and why...???
Hi,
Floats and doubles are stored as binary fractions and are not exact. Google it there is lots written and on this site too. The comparison will certainly be false, changing to double doesn't help, although one should prefer double the compiler will if one doesn't specify float.
Last edited on
0.1 is a double.
So you comparison is something like:
1
2
3
4
double _D = 0.1; //Has some inexact representation in memory
float x = 0.1f; //Has some representation with more inexactness than double one
if(_D == static_cast<double>(x)) //cast does not eliminate inexactness
//... 

You can try if(x == 0.1f) but you should read on FP number representation and typical problems to better understand problem with comparison.
And because floating point types are inexact they should normally not be compared using ==. If you need something to be exact it's better to use integers.
The simple answer is that 0.1 is not exactly represent-able within the precision of float and has to be truncated to the precision of float when assigned. For the comparison, the float is converted to double and compared with the literal 0.1 which was truncated to the precision of double.

If you change to double you will get True, as both will be truncated to the same value.

If you change to a number represent-able within the mantissa bits of the float (0.5 or 0.25 or 0.75 etc) you will also get True.

The detail is that float x = 0.1 is truncated to 23 bits of the float, and then expanded to the 52 bits of the double for the comparison, while the literal 0.1 is represented as 52 bits with no truncation to 23 bits along the way.

With some old-style casting you can prove:

1
2
3
4
5
6
  cout << std::hex << "x  =" << *(int *)&x << endl; // sizeof(int) == sizeof(float) on my machine

  double d=0.1;
  cout << std::hex << "0.1=" << *(long long *)& d << endl; // sizeof(double) == sizeof(long long) on my machine
  d = (float)0.1;
  cout << std::hex << "d  =" << *(long long *)& d << endl;

x  =3dcccccd
0.1=3fb999999999999a
d  =3fb99999a0000000

So the float becomes a double by adding zeros to the extra bits of the mantissa. In this case they will not be equal.

When using a number exactly represent-able by float (within the mantissa bits), no truncation takes place, and the float converted to double will be the same as the literal:
x    =3ec00000
0.375=3fd8000000000000
d    =3fd8000000000000

Notice all the trailing zeros. In this case they will be equal.

Ref:
http://en.wikipedia.org/wiki/Single-precision_floating-point_format
http://en.wikipedia.org/wiki/Double-precision_floating-point_format

As mentioned above, exact comparison of floats and doubles is to be avoided, and is non-portable.
Last edited on
Topic archived. No new replies allowed.