It seems like a simple question, that a primary school student can easily answer. But if you try the following code in Python, you will get a False.
0.1 + 0.2 == 0.3
False
You can also try the classic one:
0.1 + 0.1 + 0.1 == 0.3
False
The output is still false. “This is not a bug in Python, and it is not a bug in your code either. You’ll see the same kind of thing in all languages that support your hardware’s floating-point arithmetic.” The reason is that in computer hardware all floating-point numbers are represented as binary fractions. Unfortunately, most decimal fractions cannot be represented exactly as binary fractions. “A consequence is that, in general, the decimal floating-point numbers you enter are only approximated by the binary floating-point numbers actually stored in the machine.” In the case of 0.1, the binary fraction is 3602879701896397 / 2 ** 55 which is extremely close to but not exactly equal to the true value of 1/10.
0.1 == 3602879701896397 / 2 ** 55
True
A helpful function from the math module is the math.fsum()
. It helps decrease loss-of-precision during summation. It makes the outcome of the following scenario different.
sum([.1]*10) == 1
False
import math
math.fsum([0.1]*10) == 1
True
However, it is still not helpful for our 0.3 example.
math.fsum([0.1, 0.1, 0.1]) == 0.3
False
So what is the best way to compare floating-point numbers? Since python 3.5 a function in math module isclose()
was added to tell whether two values are approximately equal or “close” to each other. You decide the relative tolerance which is the maximum allowed difference between isclose()
arguments, relative to the larger absolute value.
math.isclose(0.1+0.2, 0.3, abs_tol=1e-5)
True
There is also an isclose()
function in Numpy, which allows you to compare the elements in an array.
import numpy as np
np.isclose([0.1+0.1, 0.1+0.1+0.1], [0.2, 0.3])
array([ True, True])
A very important application scenario with floating-point numbers comparison in the test process. The approx()
is the correct function from the pytest library to assert that two numbers are equal to each other within some tolerance.
from pytest import approx
0.1 + 0.2 == approx(0.3)
True