Using math.isclose function with values close to 0
The answer can be worked out by reading the documentation.
math.isclose(a, b, *, rel_tol=1e-09, abs_tol=0.0)
Return True if the values a and b are close to each other and False otherwise.
Whether or not two values are considered close is determined according to given absolute and relative tolerances.
rel_tol is the relative tolerance – it is the maximum allowed difference between a and b, relative to the larger absolute value of a or b. For example, to set a tolerance of 5%, pass rel_tol=0.05. The default tolerance is 1e-09, which assures that the two values are the same within about 9 decimal digits. rel_tol must be greater than zero.
abs_tol is the minimum absolute tolerance – useful for comparisons near zero. abs_tol must be at least zero.
If no errors occur, the result will be:
abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
You use default tolerances which means that a relative tolerance check is used. And the equation above makes it clear why your expressions evaluates false.
Consider the final expression in the question:
math.isclose(1.0e-100 , 0.0)
Plug these values into the expression from the documentation and we have
1.0e-100 <= max(1.0e-9 * 1.0e-100, 0.0)
I think it should be obvious that when performing a relative tolerance comparison, using default tolerances, no non-zero value is deemed close to zero.
For very small values you should perhaps use an absolute tolerance.
Or you should re-write the test to avoid comparing against zero.
steffen
I am a Python freak and data nerd. Also, I am experimenting with creating videos on youtube. About Python and data. ¯(°_o)/¯ https://www.youtube.com/channel/UCG9XNnq9LodijOBpIVy1ILg
Updated on November 16, 2020Comments
-
steffen over 3 years
As we know, due to the binary representation of numbers, this expression evaluates to
False
(at least in Python):0.2 + 0.4 == 0.6
In order to be able to check for equality within numerical errors, the module
math
offersisclose
:import math math.isclose(0.2 + 0.4 , 0.6)
This last expression yields
True
as expected.Now why does this following expression is
False
again?math.isclose(0.2 + 0.4 - 0.6 , 0.0)
It appears that everything compared to
0.0
isFalse
math.isclose(1.0e-100 , 0.0)
-
steffen about 8 yearsmmph. I did read the documentation and noted that I could set the relative and absolute tolerances. But I somehow missed the default absolute tolerance being 0.0. Perhaps I should go to bed... Thanks David
-
Andrea Corbellini about 8 yearsFor completeness, the original PEP explains why the absolute tolerance is 0: "The absolute tolerance required to determine if a value is "close" to zero is entirely use-case dependent."