所以 Python 有正无穷和负无穷:
float("inf"), float("-inf")
这似乎是必须有一些警告的功能类型。有什么我应该注意的吗?
Python 的实现很好地遵循IEEE-754 标准,您可以将其用作指导,但它依赖于编译它的底层系统,因此可能会出现平台差异。最近¹,已经应用了一个允许"infinity" 和 "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
or**
很棘手,因为它的行为不应该如此。当两个实数的结果太高而无法容纳双精度浮点数时(它应该返回无穷大),它会引发溢出异常,但是当输入为inf
or时-inf
,它会正确运行并返回inf
or 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
yield inf
。
注意 2:因为任何带有NaN
返回值的计算NaN
和任何与 的比较NaN
,包括NaN
它本身false
,都应该使用该math.isnan
函数来确定一个数字是否确实是NaN
。
注 3:虽然 Python 支持写入float('-NaN')
,但符号被忽略,因为内部不存在符号NaN
。如果除以-inf / +inf
,结果是NaN
,不是-NaN
(没有这样的事情)。
注意 4:小心依赖上述任何内容,因为 Python 依赖于为其编译的 C 或 Java 库,并且并非所有底层系统都正确实现了所有这些行为。如果您想确定,请在进行计算之前测试无穷大。
¹) 最近意味着从3.2 版开始。
²) 浮点数支持正负零,所以:x / float('inf')
保持它的符号和-1 / float('inf')
yield -0.0
、1 / float(-inf)
yield -0.0
、1 / float('inf')
yield0.0
和-1/ float(-inf)
yield 0.0
。此外,0.0 == -0.0
istrue
,如果您不希望它为真,则必须手动检查该符号。
您仍然可以从涉及以下的简单算术中获得非数字 (NaN) 值inf
:
>>> 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
值默默地注入到您的计算中。
C99也是如此。
所有现代处理器使用的 IEEE 754 浮点表示具有几个特殊的位模式,为正无穷(sign=0、exp=~0、frac=0)、负无穷(sign=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 错误跟踪器上提交了一个问题。可以在https://bugs.python.org/issue32968看到。
更新:这将在 Python 3.8 中修复。
一个非常糟糕的警告: 除以零
在一1/x
小部分中,取决于x = 1e-323
它,inf
但它何时x = 1e-324
或很少抛出ZeroDivisionError
>>> 1/1e-323
inf
>>> 1/1e-324
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: float division by zero
所以要小心!