math.isclose()
exists to determine if the difference between two values is within a tolerance.
As far as I understand it, the default values for this tolerance are:
rel_tol = 1e-09
abs_tol = 0.0
If I set both values to 0.0
, then it should be testing if the two values are identical.
This seems to work fine for smaller values:
import math
math.isclose(1000, 1000, rel_tol=0.0, abs_tol=0.0) # True
math.isclose(1000, 1001, rel_tol=0.0, abs_tol=0.0) # False
But it fails with very large values:
import math
import sys
math.isclose(sys.maxsize, sys.maxsize, rel_tol=0.0, abs_tol=0.0) # True
math.isclose(sys.maxsize, sys.maxsize-1, rel_tol=0.0, abs_tol=0.0) # True
math.isclose(sys.maxsize, sys.maxsize-100, rel_tol=0.0, abs_tol=0.0) # True
math.isclose(sys.maxsize, sys.maxsize-1000, rel_tol=0.0, abs_tol=0.0) # False
It seems that there is still a relative tolerance?
Why does this behavior occur?
The above code was run with Python 3.5.2.
UPDATE 1:
It seems that a similar behavior occurs when using very large float values:
import math
import sys
m = sys.float_info.max # type 'float'
math.isclose(m, m) # True
math.isclose(m, m-1.0) # True
math.isclose(m, m-1e100) # True
math.isclose(m, m-1e300) # False
math.isclose(m, m, rel_tol=0.0, abs_tol=0.0) # True
math.isclose(m, m-1.0, rel_tol=0.0, abs_tol=0.0) # True
math.isclose(m, m-1e100, rel_tol=0.0, abs_tol=0.0) # True
math.isclose(m, m-1e300, rel_tol=0.0, abs_tol=0.0) # False
On the other hand, the comparison operators do not work here either.
import math
import sys
m = sys.float_info.max # type 'float'
m == m # True
m < m # False
m > m # False
m == m-1.0 # True
m < m-1.0 # False
m > m-1.0 # False
m == m-1e100 # True
m < m-1e100 # False
m > m-1e100 # False
m == m-1e300 # False
m > m-1e300 # True
m < m-1e300 # False
UPDATE 2:
The answer to 'UPDATE 1' was given here.
sys.maxsize
is an integer, but math.isclose()
works on floating-point values. On a 64-bit box, sys.maxsize
has more bits of precision than a float can represent, so float(sys.maxsize - N) == float(sys.maxsize)
for all sufficiently small postive integer N
.
>>> from sys import maxsize as m
>>> m
9223372036854775807
>>> float(m)
9.223372036854776e+18
>>> float(m - 1) # identical
9.223372036854776e+18
>>> float(m - 100) # identical
9.223372036854776e+18
>>> float(m - 1000) # finally subtracting enough to make a tiny difference
9.223372036854775e+18
Short course: when you want to compare integers for equality, converting to float first simply doesn't make sense.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With