Is Python's == an equivalence relation on the floats?
Question:
In native Python, without using NumPy (for which numpy.nan != numpy.nan
) there is no NaN, so am I right in thinking that Python’s floating point ==
is reflexive? Then since it is symmetric (a == b
implies b == a
) and transitive (if a==b
and b==c
then a==c
), can we say that Python’s ==
is an equivalence relation on the float
s?
EDIT: OK, so I learned that there is a NaN: float('nan')
(thanks @unutbu) which will propagate through various operations, but does any native Python method return it (rather than raising an Exception) without me introducing it by this assignment?
Answers:
float('nan')
exists in native Python and float('nan') != float('nan')
. So no, ==
is not an equivalence relation since it lacks reflexivity:
In [40]: float('nan') == float('nan')
Out[40]: False
==
is reflexive for all numbers, zero, -zero, ininity, and -infinity, but not for nan.
You can get inf
, -inf
, and nan
in native Python just by arithmetic operations on literals, like below.
These behave correctly, as in IEEE 754 and without math domain exception:
>>> 1e1000 == 1e1000
True
>>> 1e1000/1e1000 == 1e1000/1e1000
False
1e1000
is a very big number, so float and double represent it as an infinity.
- infinity is equal to infinity
- infinity divided by infinity is not a number
- not a number != not a number
Floating-point arithmetic in Python also works OK for infinity minus infinity etc.:
>>> x = 1e1000
>>> x
inf
>>> x+x
inf
>>> x-x
nan
>>> x*2
inf
>>> x == x
True
>>> x-x == x-x
False
>>>
And for the zero and minus zero case:
>>> inf = float("inf")
>>> 1/inf
0.0
>>> -1/inf
-0.0
>>> -1/inf == 1/inf
True
>>>
In native Python, without using NumPy (for which numpy.nan != numpy.nan
) there is no NaN, so am I right in thinking that Python’s floating point ==
is reflexive? Then since it is symmetric (a == b
implies b == a
) and transitive (if a==b
and b==c
then a==c
), can we say that Python’s ==
is an equivalence relation on the float
s?
EDIT: OK, so I learned that there is a NaN: float('nan')
(thanks @unutbu) which will propagate through various operations, but does any native Python method return it (rather than raising an Exception) without me introducing it by this assignment?
float('nan')
exists in native Python and float('nan') != float('nan')
. So no, ==
is not an equivalence relation since it lacks reflexivity:
In [40]: float('nan') == float('nan')
Out[40]: False
==
is reflexive for all numbers, zero, -zero, ininity, and -infinity, but not for nan.
You can get inf
, -inf
, and nan
in native Python just by arithmetic operations on literals, like below.
These behave correctly, as in IEEE 754 and without math domain exception:
>>> 1e1000 == 1e1000
True
>>> 1e1000/1e1000 == 1e1000/1e1000
False
1e1000
is a very big number, so float and double represent it as an infinity.
- infinity is equal to infinity
- infinity divided by infinity is not a number
- not a number != not a number
Floating-point arithmetic in Python also works OK for infinity minus infinity etc.:
>>> x = 1e1000
>>> x
inf
>>> x+x
inf
>>> x-x
nan
>>> x*2
inf
>>> x == x
True
>>> x-x == x-x
False
>>>
And for the zero and minus zero case:
>>> inf = float("inf")
>>> 1/inf
0.0
>>> -1/inf
-0.0
>>> -1/inf == 1/inf
True
>>>