Comman Floating point precision Problem

Hey guys please explain this regarding floating point precision-

First Code:

float x = 0.1;
if (x == 0.1)
    printf("IF");
else
    printf("ELSE");

**output**: ELSE

Second Code:

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

**output**: IF

Please help me understand this concept.

The important factors under consideration with float or double numbers are:

Precision & Rounding

Precision:

The precision of a floating point number is how many digits it can represent without losing any information it contains.

Consider the fraction 1/3. The decimal representation of this number is 0.33333333333333… with 3′s going out to infinity. An infinite length number would require infinite memory to be depicted with exact precision, but float or double data types typically only have 4 or 8 bytes. Thus Floating point & double numbers can only store a certain number of digits, and the rest are bound to get lost. Thus, there is no definite accurate way of representing float or double numbers with numbers that require more precision than the variables can hold.

Rounding:

There is a non-obvious differences between binary and decimal (base 10) numbers.
Consider the fraction 1/10. In decimal, this can be easily represented as 0.1, and 0.1 can be thought of as an easily representable number. However, in binary, 0.1 is represented by the infinite sequence: 0.00011001100110011…

#include < iomanip >
#include < iostream >


int main()
{
  float x=0.1;
  std::cout << std::setprecision(100) << (double)0.1 << std::endl;
  std::cout << std::setprecision(100) << (float)0.1 << std::endl;
  std::cout << std::setprecision(100) << (double)((float)0.1) << std::endl<< std::endl;
  
  std::cout << std::setprecision(100) << (double)x << std::endl;
  std::cout << std::setprecision(100) << (float)x << std::endl;
  std::cout << std::setprecision(100) << (double)((float)x) << std::endl;
}

Output :

0.1000000000000000055511151231257827021181583404541015625

0.100000001490116119384765625

0.100000001490116119384765625

0.100000001490116119384765625

0.100000001490116119384765625

0.100000001490116119384765625

Neither float nor double can represent 1.1 accurately. When you try to do the comparison the float number is implicitly up-converted to a double. The double data type can accurately represent the contents of the float, so the comparison yields false.

Similarly in your case,


float x = 0.1;
if (x == 0.1)
    printf("IF");
else
    printf("ELSE");


this if (x == 0.1) comparison is evaluated as if ( 0.100000001490116119384765625 == 0.1) which is clearly false and ELSE is printed.

But when you change x to 0.5, in the above sample program

#include < iomanip >
#include < iostream >


int main()
{
  float x=0.5;
  std::cout << std::setprecision(100) << (double)0.5 << std::endl;
  std::cout << std::setprecision(100) << (float)0.5 << std::endl;
  std::cout << std::setprecision(100) << (double)((float)0.5 << std::endl<< std::endl;
  
  std::cout << std::setprecision(100) << (double)x << std::endl;
  std::cout << std::setprecision(100) << (float)x << std::endl;
  std::cout << std::setprecision(100) << (double)((float)x) << std::endl;
}

Output:

0.5

0.5

0.5

0.5

0.5

0.5

This is why in your second case, output is IF.

For more information/clearification, go through this and this awesome links and also this and this at SO.

Button line : NEVER COMPARE FLOAT WITH FLOAT , FLOAT WITH DOUBLE, DOUBLE WITH DOUBLE STRAIGHTWAY. Use some other techniques instead.

1 Like

@mediocoder Can you kindly tell the techniques that can be used to compare the floating-point variables?