# Why floating point comparisons should be avoided?

Why floating point comparisons are inaccurate and should be avoided?

For eg. this returns `false`

`2.0 * 5.0 == 10.0`

PS : By comparisons I mean equality and inequality, not `<` and `>`.

As pointed out by other answers, your example returns true and you should deal with floats carefully because they are NOT precise.

The precision problem is caused by the fact that there are some floating-point values that cannot be exactly represented in binary. The decimal numbering system has this problem too with some values.

For example, the value 1/3 (or 0.333...) can never be represented precisely as a floating-point value because obviously it requires an infinite number of digits after the decimal point. A value like 1/2 on the other hand can be precisely represented as 0.5.

In the decimal numbering system, the position of the first digit after the decimal point is 10^-1, the following position is 10^-2, and so on. For example, 1/2 (dec) = 5/10 (dec) = 5 * 10^-1 (dec) = 0.5 (dec).

Similarly, in the binary numbering system, the position of the first digit after the floating point is 2^-1, the following position 2^-2 and so on. So 1/2 (dec) = 1 * 2^-1 (dec) = 0.1 (bin).

As you might have noticed, you should be able to represent a fractional value a/b (dec) as c/10^d (dec) to be able to represent it precisely as a floating-point value in decimal, where a, b, c, and d are all integers.

Similarly, you should be able to represent the value a/b (dec) as f/2^g (dec), to be able to represent it as a floating-point value precisely in binary, where a, b, f, and g are all integers.

For example, since you can't represent a value like 1/10 (dec) or 0.1 (dec) as f/2^g (dec), because obviously you can't represent 10 (dec) as 2^g (dec), you can't represent that precisely as a floating-point value in binary.

This imprecision might lead to serious problems and that's why you should be careful when dealing with floating-point values.

First things first, your example is returning `true`.

It is difficult to deal with floating point numbers in any programming language unless you know how they are stored/operated on your machine. Although example you gave, returned `true` on ideone, but it is for sure that there could be any another example for such weird behaviour.

``````float a = 0.1;
printf("%.18f", a);
``````

yields `0.100000001490116` as output.

Errors can also be amplified as

``````float a = 0.000001, sum = 0.0;
for (i = 0 ; i < 1000000 ; ++i)
sum += a;
printf("%.18f", sum);
``````

yields `1.009038925170898438` as output.

This is because floating point numbers are not stored the way simply as integers are. C99 follows IEEE 754-1985(IEC 60559) standard to deal with floating point numbers.

There are 2 types of numbers, namely single precision and double precision.

`````` --------------------------------------------------------------------------------------
|      Level         |      Width      |                   Range                       |
|--------------------+-----------------+-----------------------------------------------
|                    |                 |                                               |
| Single Precision   |      32-bits    |       ±1.18*(10**(-38)) to ±3.4*(10**(38))    |
|                    |                 |                                               |
| Double Precision   |      64-bits    |      ±2.23*(10**(-308)) to ±1.80*(10**(308))  |
--------------------+-----------------+-----------------------------------------------
``````

In memory, these numbers are stored in 3 fields :

• Signed bit
• Exponent (Biased)
• Mantissa (Fractional Part)

Single precision floating point numbers consists of 32-bits, out of which 1 bit is dedicated to store the sign, 8 bits for exponent, and the rest(23 bits) for mantissa. For the double precision floating point numbers, out of 64 bits, there is 1 sign bit, 11 bits for exponent, and 52 bits for storing mantissa.

Now, when you want to store a number, the number is first converted to its binary equivalent and then changed to a notation such that there remains only a single bit on left side of the period.

Say you got 0.15625 in base 10, then its binary equivalent comes out to be 0.00101, which is then written as 1.01 * 2-3. In this case, the sign bit is set to 0 as the number is positive. For a single precision number, we have 8 bits, since we need to manage both positive and negative (and 0) values in this, lets set 28/2 - 1 = 127 as the bias. A similar calculation for double precision number gives 211/2 - 1 = 1023 as the bias. The biased exponent is the sum of this bias and the exponent from the notation. In the above example, the biased exponent is 127 + (-3) = 124 for single precision and 1023 + (-3) = 1020 for double precision. The fractional part is stored as 0.0100...

In short, numbers aren't stored directly, but in a different notation. Conversion to and/or from this notation to original values may result in loss of precision. This is because approximations of those numbers are stored. However, it should be noted that real values to approximated values are like many to one mapping, So it possible that two different numbers are approximated to a same value and when retrieved back, result a same number(unlike expectation). On the same time, this also points to the fact that both numbers should lie in a particular range. Hence, all numbers in a particular range approximate to a same number and when retrieved back, result to a same value for all. For instance, consider this

``````float a = 0.1, b = 0.100000005;
printf("%.18f %.18f", a, b);
``````

results in `0.100000001490116119 0.100000001490116119`.

Therefore, all numbers lying in the range [0.1, 0.100000005] will be stored as same number, and expressions like `0.1 == 0.100000005` return `true`. That is why it is advised not to use `==` and `!=` operator with floating point numbers. Instead, one could check range in such situation using `>` and/or `<` against a fixed precision.