Python无限 - 任何警告?

Cas*_*ash 176 python infinity

所以Python有正负无限:

float("inf"), float("-inf")
Run Code Online (Sandbox Code Playgroud)

这似乎是一种必须要注意的功能类型.有什么我应该知道的吗?

Abe*_*bel 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.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')
    
    Run Code Online (Sandbox Code Playgroud)

笔记

注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库,并非所有底层系统都能正确实现所有这些行为.如果您想确定,请在进行计算之前测试无穷大.

¹)最近意味着自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.0true,你必须手动检查就签收,如果你不希望它是真的.

  • 好吧,差不多:1 /浮点('无限')== 0.0 (12认同)
  • 一个小的挑剔:不是每个无穷大的计算都会产生无穷大:`-1*float('infinity')== -inf` (11认同)
  • 这就是为什么我说这是一个_small_ nitpick.你让我担心一分钟,在使用无限时,这个标志会被完全忽略,我想为其他人澄清一下. (4认同)
  • @Phil:虽然我很确定你只是想证明并非所有的inf计算都会产生inf或NaN,我只是想让其他可能正在阅读评论的人明白,1/float('infinity ')== 0.0是真的; 因为,当你接近无穷大时,除法的结果接近0.我知道它只是基本的微积分,但我想确保那些阅读理解,或者至少知道为什么,结果就是它的原因. (3认同)

Gre*_*ill 97

您仍然可以从简单的算术中获取非数字(NaN)值,包括inf:

>>> 0 * float("inf")
nan
Run Code Online (Sandbox Code Playgroud)

请注意,您通常不会得到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')
Run Code Online (Sandbox Code Playgroud)

inf值被认为是具有异常语义的非常特殊的值,因此最好直接了解OverflowError异常,而不是将inf值静默注入计算中.

  • 一个简单的浮点加法,乘法等会愉快地产生inf:f = 1.3407807929942597e + 154; f*f => inf.引发OverflowError似乎是**的一个例外. (8认同)
  • @Lutz如果它出现乘法,那么它仍然是不一致的行为.当然,大*大也不是无穷大. (6认同)
  • @Abel那不是马车.溢出意味着数量非常大.太大而不能表示它,但仍然小于无穷大.将无穷大放入这样的位置对于特定应用程序逻辑的异常处理程序可能很有用,但对于Python来说通常是不正确的. (2认同)