Python Infinity-任何警告?


178

因此,Python具有正负无穷大:

float("inf"), float("-inf")

这似乎就像必须要注意的功能类型。我有什么需要注意的吗?


25
需要注意的是不断的1e309将被解释为+inf-1e309将被解释为-inf
克里斯·泰勒

Answers:


97

您仍然可以通过涉及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值静默注入计算中。


8
一个简单的浮点加法,乘法等将愉快地产生inf:f = 1.3407807929942597597e + 154; f * f => inf。引发OverflowError似乎是**的例外。
俄勒冈州,2015年

实际上,@ eregon **似乎有点马车。当它用实数溢出时,会引发错误,但是当其任何操作数是inf或时-inf,它将返回0.0inf。因此,当输入为无穷大时,它确实可以正常工作,但是当结果为无穷大时,则不能正常工作。
亚伯

2
@Abel这不是越野车。溢出意味着数量非常大。太大,无法表示它,但仍小于无穷大。将无穷大放在这样的位置对于您的特定应用程序逻辑的异常处理程序可能很有用,但对于Python通常来说是不正确的。
Lutz Prechelt

6
@Lutz如果以乘法形式出现,那么它仍然是不一致的行为。当然,大*大也不是无穷大。
理查德·拉斯特

100

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.powpow或者**是棘手的,因为它不表现为它应该。当两个实数的结果太大而无法容纳双精度浮点数时(它应返回无穷大),它将引发溢出异常,但是当输入为inf或时-inf,它的行为将正确并返回inf0.0。当第二个参数为时NaN,它将返回NaN,除非第一个参数为1.0。还有更多的问题,文档中并未涵盖所有问题。
  • math.exp遭受与相同的问题math.pow。解决此溢出问题的解决方案是使用类似于以下代码:

    try:
        res = math.exp(420000)
    except OverflowError:
        res = float('inf')

笔记

注1:作为附加的警告,如IEEE标准所定义,如果您的计算结果不足或溢出,则结果将不是不足或溢出错误,而是正负无穷大:1e308 * 10.0yields 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')收益率-0.01 / float(-inf)收益率-0.01 / float('inf')收益率0.0-1/ float(-inf)收益率0.0。此外,0.0 == -0.0is是true,如果您不希望它为真,必须手动检查它。


11
一个小巧的选择:并非所有具有无穷大的计算都会产生无穷大:-1 * float('infinity') == -inf
Evan Krall

4
这就是为什么我说那是小问题。您让我担心了一分钟,当使用无穷大时,该信号将被完全忽略,我想向其他人澄清。
埃文·克拉尔

12
好吧,差不多:1 / float('infinity')== 0.0
Phil

3
@Phil:尽管我很确定您只是试图表明并非所有带有inf的计算都会导致inf或NaN,但我只是想向其他可能正在阅读注释的人表明,1 / float('infinity ')== 0.0为真;因为,当您接近无穷大时,除法的结果趋近于0。我知道这只是基本的演算,但我想确保那些阅读的读者理解或至少知道为什么,结果就是它。
安东尼·佩斯

1
我觉得这个答案比公认的答案要好得多。
Christian Herenz

3

所以呢C99

所有现代处理器使用的IEEE 754浮点表示法具有几个特殊的位模式,分别保留用于正无穷大(符号= 0,exp =〜0,frac = 0),负无穷大(符号= 1,exp =〜0,frac = 0) )和许多NaN(非数字:exp =〜0,frac≠0)。

您只需要担心:某些算术运算可能会导致浮点异常/陷阱,但不仅限于这些“有趣的”常量。


1
那么,如果我的算术太大,它可能会变成inf?
Casebash

@Casebash不,它将导致OverflowError
wizzwizz4

2

我发现到目前为止,没有人提到过一个警告。我不知道在实际情况下是否经常出现这种情况,但这是出于完整性考虑。

通常,计算模无穷大会以浮点数形式返回自己,但分数无穷小会返回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 Tracker上提出了一个问题。可以在https://bugs.python.org/issue32968上看到。

更新:这将在Python 3.8中修复


2

非常糟糕的警告: 被零除

在一1/x小部分,最多x = 1e-323inf但当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

所以要小心!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.