Python Infinity - 有什么注意事项吗?
题
所以Python有正无穷和负无穷:
float("inf"), float("-inf")
这似乎是必须有一些警告的功能类型。有什么我应该注意的吗?
解决方案
您仍然可以从涉及 inf
的简单算术中获取非数字(NaN)值:
>>> 0 * float("inf")
nan
请注意,您通常不通过常规算术计算得到 inf
值:
>>> 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')
inf
值被认为是一个非常特殊的值,具有不寻常的语义,因此最好通过异常直接了解 OverflowError
,而不是拥有 inf
值静默注入计算中。
其他提示
Python的实现 遵循 IEEE-754 标准 很好,您可以将其用作指导,但它依赖于编译它的底层系统,所以 平台差异 可能发生。最近,应用了一个修复程序,允许 “无穷大”和“inf”, ,但这在这里并不重要。
以下部分同样适用于正确实现 IEEE 浮点运算的任何语言,它不仅仅特定于 Python。
不平等比较
当处理无穷大和大于时 >
或小于 <
运算符,以下计数:
- 任何数字,包括
+inf
高于-inf
- 任何数字,包括
-inf
低于+inf
+inf
是 既不高也不低 比+inf
-inf
既不高于也不低于-inf
- 任何涉及的比较
NaN
是假的(inf
既不高于也不低于NaN
)
比较平等
当比较平等时, +inf
和 +inf
是相等的,因为 -inf
和 -inf
. 。这是一个备受争议的问题,对您来说可能听起来有争议,但它是在 IEEE 标准中的,Python 的行为也是如此。
当然, +inf
不等于 -inf
和一切,包括 NaN
本身不等于 NaN
.
无穷大的计算
大多数无穷大的计算都会产生无穷大,除非两个操作数都是无穷大,当运算除法或模数或与零相乘时,需要记住一些特殊规则:
- 当乘以零时,其结果是未定义的,它产生
NaN
- 当任何数字(除了无穷大本身)除以无穷大时,会产生
0.0
或者-0.0
². - 当正无穷大或负无穷大除以(包括模数)正无穷大或负无穷大时,结果是不确定的,所以
NaN
. - 相减时,结果可能会令人惊讶,但遵循 数学常识:
- 当做
inf - inf
, ,结果未定义:NaN
; - 当做
inf - -inf
, ,结果是inf
; - 当做
-inf - inf
, ,结果是-inf
; - 当做
-inf - -inf
, ,结果未定义:NaN
.
- 当做
- 添加时,也会同样令人惊讶:
- 当做
inf + inf
, ,结果是inf
; - 当做
inf + -inf
, ,结果未定义:NaN
; - 当做
-inf + inf
, ,结果未定义:NaN
; - 当做
-inf + -inf
, ,结果是-inf
.
- 当做
- 使用
math.pow
,pow
或者**
很棘手,因为它的行为不正常。当两个实数的结果太高而无法容纳双精度浮点数时(它应该返回无穷大),但当输入是inf
或者-inf
, ,它的行为正确并返回inf
或者0.0
. 。当第二个参数是NaN
, ,它返回NaN
, ,除非第一个参数是1.0
. 。还有更多问题,不是全部 文档中涵盖. math.exp
遇到同样的问题math.pow
. 。修复此溢出的解决方案是使用类似于以下的代码:try: res = math.exp(420000) except OverflowError: res = float('inf')
笔记
注1: 作为额外的警告,根据 IEEE 标准的定义,如果您的计算结果低于或溢出,结果将不会是低于或溢出错误,而是正无穷大或负无穷大: 1e308 * 10.0
产量 inf
.
笔记2: 因为任何计算 NaN
回报 NaN
以及任何比较 NaN
, , 包括 NaN
本身就是 false
, ,你应该使用 math.isnan
判断一个数字是否确实的函数 NaN
.
注3: 虽然Python支持写 float('-NaN')
, ,该符号被忽略,因为不存在任何符号 NaN
内部。如果你分 -inf / +inf
, ,结果是 NaN
, , 不是 -NaN
(哪有这回事)。
注4: 请小心依赖上述任何一项,因为 Python 依赖于为其编译的 C 或 Java 库,并且并非所有底层系统都正确实现所有这些行为。如果您想确定,请在计算之前测试无穷大。
1) 最近是指自 3.2版本.
²) 浮点数支持正零和负零,因此: x / float('inf')
保留其标志并 -1 / float('inf')
产量 -0.0
, 1 / float(-inf)
产量 -0.0
, 1 / float('inf')
产量 0.0
和 -1/ float(-inf)
产量 0.0
. 。此外, 0.0 == -0.0
是 true
, ,如果您不希望该符号为真,则必须手动检查该符号。
C99 也是如此。
所有现代处理器使用的IEEE 754浮点表示具有为正无穷大保留的几种特殊位模式(符号= 0,exp =〜0,frac = 0),负无穷大(符号= 1,exp = ~0, frac = 0),和许多NaN(非数字:exp =〜0,frac≠0)。
您需要担心的是:某些算术可能会导致浮点异常/陷阱,但这些并不仅限于这些“有趣”的异常/陷阱。常数。
我发现了一个警告,到目前为止还没有人提到过。我不知道它是否会在实际情况下经常出现,但这是为了完整起见。
通常,计算模数无穷大的数字会将其自身返回为浮点数,但模数无穷大的分数将返回 nan
(不是数字)。这是一个例子:
>>> from fractions import Fraction
>>> from math import inf
>>> 3 % inf
3.0
>>> 3.5 % inf
3.5
>>> Fraction('1/3') % inf
nan
我在Python bug跟踪器上提出了一个问题。可以在 https://bugs.python.org/issue32968 上看到。
更新:这将是在Python 3.8中修复。