Python Infinity – Any caveats?
Question:
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?
Answers:
So does C99.
The IEEE 754 floating point representation used by all modern processors has several special bit patterns reserved for positive infinity (sign=0, exp=~0, frac=0), negative infinity (sign=1, exp=~0, frac=0), and many NaN (Not a Number: exp=~0, frac≠0).
All you need to worry about: some arithmetic may cause floating point exceptions/traps, but those aren’t limited to only these “interesting” constants.
You can still get notanumber (NaN) values from simple arithmetic involving inf
:
>>> 0 * float("inf")
nan
Note that you will normally not get an inf
value through usual arithmetic calculations:
>>> 2.0**2
4.0
>>> _**2
16.0
>>> _**2
256.0
>>> _**2
65536.0
>>> _**2
4294967296.0
>>> _**2
1.8446744073709552e+19
>>> _**2
3.4028236692093846e+38
>>> _**2
1.157920892373162e+77
>>> _**2
1.3407807929942597e+154
>>> _**2
Traceback (most recent call last):
File "<stdin>", line 1, in ?
OverflowError: (34, 'Numerical result out of range')
The inf
value is considered a very special value with unusual semantics, so it’s better to know about an OverflowError
straight away through an exception, rather than having an inf
value silently injected into your calculations.
Python’s implementation follows the IEEE754 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.
Comparison for inequality
When dealing with infinity and greaterthan >
or lessthan <
operators, the following counts:
 any number including
+inf
is higher thaninf
 any number including
inf
is lower than+inf
+inf
is neither higher nor lower than+inf
inf
is neither higher nor lower thaninf
 any comparison involving
NaN
is false (inf
is neither higher, nor lower thanNaN
)
Comparison for equality
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
.
Calculations with infinity
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:

when multiplied by zero, for which the result is undefined, it yields
NaN

when dividing any number (except infinity itself) by infinity, which yields
0.0
or0.0
². 
when dividing (including modulo) positive or negative infinity by positive or negative infinity, the result is undefined, so
NaN
. 
when subtracting, the results may be surprising, but follow common math sense:

when doing
inf  inf
, the result is undefined:NaN
; 
when doing
inf  inf
, the result isinf
; 
when doing
inf  inf
, the result isinf
; 
when doing
inf  inf
, the result is undefined:NaN
. 
when adding, it can be similarly surprising too:

when doing
inf + inf
, the result isinf
; 
when doing
inf + inf
, the result is undefined:NaN
; 
when doing
inf + inf
, the result is undefined:NaN
; 
when doing
inf + inf
, the result isinf
. 
using
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 isinf
orinf
, it behaves correctly and returns eitherinf
or0.0
. When the second argument isNaN
, it returnsNaN
, unless the first argument is1.0
. There are more issues, not all covered in the docs. 
math.exp
suffers the same issues asmath.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')
Notes
Note 1: as an additional caveat, that as defined by the IEEE standard, if your calculation result underor 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.
I found a caveat that no one so far has mentioned. I don’t know if it will come up often in practical situations, but here it is for the sake of completeness.
Usually, calculating a number modulo infinity returns itself as a float, but a fraction modulo infinity returns nan
(not a number). Here is an example:
>>> from fractions import Fraction
>>> from math import inf
>>> 3 % inf
3.0
>>> 3.5 % inf
3.5
>>> Fraction('1/3') % inf
nan
I filed an issue on the Python bug tracker. It can be seen at https://bugs.python.org/issue32968.
Update: this will be fixed in Python 3.8.
A VERY BAD CAVEAT : Division by Zero
in a 1/x
fraction, up to x = 1e323
it is inf
but when x = 1e324
or little it throws ZeroDivisionError
>>> 1/1e323
inf
>>> 1/1e324
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: float division by zero
so be cautious!