无穷大和 NaN(不是数字)

在所有版本的 Python 中,我们可以表示无限和 NaN(非数字),如下所示:

pos_inf = float('inf')     # positive infinity
neg_inf = float('-inf')    # negative infinity
not_a_num = float('nan')   # NaN ("not a number")

在 Python 3.5 及更高版本中,我们还可以使用定义的常量 math.infmath.nan

Python 3.x >= 3.5

pos_inf = math.inf
neg_inf = -math.inf
not_a_num = math.nan

字符串表示显示为 inf-infnan

pos_inf, neg_inf, not_a_num
# Out: (inf, -inf, nan)

我们可以使用 isinf 方法测试正或负无穷大:

math.isinf(pos_inf)
# Out: True

math.isinf(neg_inf)
# Out: True

我们可以通过直接比较专门测试正无穷大或负无穷大:

pos_inf == float('inf')    # or  == math.inf in Python 3.5+
# Out: True

neg_inf == float('-inf')   # or  == -math.inf in Python 3.5+
# Out: True

neg_inf == pos_inf
# Out: False

Python 3.2 及更高版本还允许检查有限性:

Python 3.x >= 3.2

math.isfinite(pos_inf)
# Out: False

math.isfinite(0.0)
# Out: True

比较运算符按正常和负无穷大的预期工作:

import sys

sys.float_info.max
# Out: 1.7976931348623157e+308  (this is system-dependent)

pos_inf > sys.float_info.max
# Out: True

neg_inf < -sys.float_info.max
# Out: True

但是如果算术表达式产生的值大于可以表示为 float 的最大值,它将变为无穷大:

pos_inf == sys.float_info.max * 1.0000001
# Out: True

neg_inf == -sys.float_info.max * 1.0000001
# Out: True

然而,除以零不会给出无穷大的结果(或者在适当的情况下给出负无穷大),而是提出了一个 ZeroDivisionError 异常。

try:
    x = 1.0 / 0.0
    print(x)
except ZeroDivisionError:
    print("Division by zero")

# Out: Division by zero

无穷大的算术运算只能给出无限的结果,有时甚至是 NaN:

-5.0 * pos_inf == neg_inf
# Out: True

-5.0 * neg_inf == pos_inf
# Out: True

pos_inf * neg_inf == neg_inf
# Out: True

0.0 * pos_inf
# Out: nan

0.0 * neg_inf
# Out: nan

pos_inf / pos_inf
# Out: nan

NaN 永远不等于任何东西,甚至不是自己。我们可以用 isnan 方法测试它:

not_a_num == not_a_num
# Out: False

math.isnan(not_a_num)
Out: True

NaN 总是比较为不相等,但绝不会小于或大于:

not_a_num != 5.0   # or any random value
# Out: True

not_a_num > 5.0   or   not_a_num < 5.0   or   not_a_num == 5.0
# Out: False

对 NaN 的算术运算总是给出 NaN。这包括乘以 -1:没有“负 NaN”。

5.0 * not_a_num
# Out: nan

float('-nan')
# Out: nan

Python 3.x >= 3.5

-math.nan
# Out: nan

旧的 float 版 NaN 和 infinity 与 Python 3.5+ math 库常量之间有一个细微的区别:

Python 3.x >= 3.5

math.inf is math.inf, math.nan is math.nan
# Out: (True, True)

float('inf') is float('inf'), float('nan') is float('nan')
# Out: (False, False)