So Python has positive and negative infinity:
float("inf"), float("-inf")
This just seems like the type of feature that has to have some caveat. Is there anything I should be aware of?
Python's implementation follows the IEEE-754 standard pretty well, which you can use as a guidance, but it relies on the underlying system it was compiled on, so platform differences may occur. Recently¹, a fix has been applied that allows "infinity" as well as "inf", but that's of minor importance here.
The following sections equally well apply to any language that implements IEEE floating point arithmetic correctly, it is not specific to just Python.
When dealing with infinity and greater-than >
or less-than <
operators, the following counts:
+inf
is higher than -inf
-inf
is lower than +inf
+inf
is neither higher nor lower than +inf
-inf
is neither higher nor lower than -inf
NaN
is false (inf
is neither higher, nor lower than NaN
)When compared for equality, +inf
and +inf
are equal, as are -inf
and -inf
. This is a much debated issue and may sound controversial to you, but it's in the IEEE standard and Python behaves just like that.
Of course, +inf
is unequal to -inf
and everything, including NaN
itself, is unequal to NaN
.
Most calculations with infinity will yield infinity, unless both operands are infinity, when the operation division or modulo, or with multiplication with zero, there are some special rules to keep in mind:
NaN
0.0
or -0.0
².NaN
.inf - inf
, the result is undefined: NaN
;inf - -inf
, the result is inf
;-inf - inf
, the result is -inf
;-inf - -inf
, the result is undefined: NaN
.inf + inf
, the result is inf
;inf + -inf
, the result is undefined: NaN
;-inf + inf
, the result is undefined: NaN
;-inf + -inf
, the result is -inf
.math.pow
, pow
or **
is tricky, as it doesn't behave as it should. It throws an overflow exception when the result with two real numbers is too high to fit a double precision float (it should return infinity), but when the input is inf
or -inf
, it behaves correctly and returns either inf
or 0.0
. When the second argument is NaN
, it returns NaN
, unless the first argument is 1.0
. There are more issues, not all covered in the docs.math.exp
suffers the same issues as math.pow
. A solution to fix this for overflow is to use code similar to this:
try:
res = math.exp(420000)
except OverflowError:
res = float('inf')
Note 1: as an additional caveat, that as defined by the IEEE standard, if your calculation result under-or overflows, the result will not be an under- or overflow error, but positive or negative infinity: 1e308 * 10.0
yields inf
.
Note 2: because any calculation with NaN
returns NaN
and any comparison to NaN
, including NaN
itself is false
, you should use the math.isnan
function to determine if a number is indeed NaN
.
Note 3: though Python supports writing float('-NaN')
, the sign is ignored, because there exists no sign on NaN
internally. If you divide -inf / +inf
, the result is NaN
, not -NaN
(there is no such thing).
Note 4: be careful to rely on any of the above, as Python relies on the C or Java library it was compiled for and not all underlying systems implement all this behavior correctly. If you want to be sure, test for infinity prior to doing your calculations.
¹) Recently means since version 3.2.
²) Floating points support positive and negative zero, so: x / float('inf')
keeps its sign and -1 / float('inf')
yields -0.0
, 1 / float(-inf)
yields -0.0
, 1 / float('inf')
yields 0.0
and -1/ float(-inf)
yields 0.0
. In addition, 0.0 == -0.0
is true
, you have to manually check the sign if you don't want it to be true.