问题:Python Infinity-任何警告?

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

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

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

So Python has positive and negative infinity:

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

This just seems like the type of feature that has to have some caveat. Is there anything I should be aware of?


回答 0

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

You can still get not-a-number (NaN) values from simple arithmetic involving inf:

>>> 0 * float("inf")
nan

Note that you will normally not get an inf value through usual arithmetic calculations:

>>> 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')

The inf value is considered a very special value with unusual semantics, so it’s better to know about an OverflowError straight away through an exception, rather than having an inf value silently injected into your calculations.


回答 1

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,如果您不希望它为真,必须手动检查它。

Python’s implementation follows the IEEE-754 standard pretty well, which you can use as a guidance, but it relies on the underlying system it was compiled on, so platform differences may occur. Recently¹, a fix has been applied that allows “infinity” as well as “inf”, but that’s of minor importance here.

The following sections equally well apply to any language that implements IEEE floating point arithmetic correctly, it is not specific to just Python.

Comparison for inequality

When dealing with infinity and greater-than > or less-than < operators, the following counts:

  • any number including +inf is higher than -inf
  • any number including -inf is lower than +inf
  • +inf is neither higher nor lower than +inf
  • -inf is neither higher nor lower than -inf
  • any comparison involving NaN is false (inf is neither higher, nor lower than NaN)

Comparison for equality

When compared for equality, +inf and +inf are equal, as are -inf and -inf. This is a much debated issue and may sound controversial to you, but it’s in the IEEE standard and Python behaves just like that.

Of course, +inf is unequal to -inf and everything, including NaN itself, is unequal to NaN.

Calculations with infinity

Most calculations with infinity will yield infinity, unless both operands are infinity, when the operation division or modulo, or with multiplication with zero, there are some special rules to keep in mind:

  • when multiplied by zero, for which the result is undefined, it yields NaN
  • when dividing any number (except infinity itself) by infinity, which yields 0.0 or -0.0².
  • when dividing (including modulo) positive or negative infinity by positive or negative infinity, the result is undefined, so NaN.
  • when subtracting, the results may be surprising, but follow common math sense:
    • when doing inf - inf, the result is undefined: NaN;
    • when doing inf - -inf, the result is inf;
    • when doing -inf - inf, the result is -inf;
    • when doing -inf - -inf, the result is undefined: NaN.
  • when adding, it can be similarly surprising too:
    • when doing inf + inf, the result is inf;
    • when doing inf + -inf, the result is undefined: NaN;
    • when doing -inf + inf, the result is undefined: NaN;
    • when doing -inf + -inf, the result is -inf.
  • using math.pow, pow or ** is tricky, as it doesn’t behave as it should. It throws an overflow exception when the result with two real numbers is too high to fit a double precision float (it should return infinity), but when the input is inf or -inf, it behaves correctly and returns either inf or 0.0. When the second argument is NaN, it returns NaN, unless the first argument is 1.0. There are more issues, not all covered in the docs.
  • math.exp suffers the same issues as math.pow. A solution to fix this for overflow is to use code similar to this:

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

Notes

Note 1: as an additional caveat, that as defined by the IEEE standard, if your calculation result under-or overflows, the result will not be an under- or overflow error, but positive or negative infinity: 1e308 * 10.0 yields inf.

Note 2: because any calculation with NaN returns NaN and any comparison to NaN, including NaN itself is false, you should use the math.isnan function to determine if a number is indeed NaN.

Note 3: though Python supports writing float('-NaN'), the sign is ignored, because there exists no sign on NaN internally. If you divide -inf / +inf, the result is NaN, not -NaN (there is no such thing).

Note 4: be careful to rely on any of the above, as Python relies on the C or Java library it was compiled for and not all underlying systems implement all this behavior correctly. If you want to be sure, test for infinity prior to doing your calculations.

¹) Recently means since version 3.2.
²) Floating points support positive and negative zero, so: x / float('inf') keeps its sign and -1 / float('inf') yields -0.0, 1 / float(-inf) yields -0.0, 1 / float('inf') yields 0.0 and -1/ float(-inf) yields 0.0. In addition, 0.0 == -0.0 is true, you have to manually check the sign if you don’t want it to be true.


回答 2

所以呢C99

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

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

So does C99.

The IEEE 754 floating point representation used by all modern processors has several special bit patterns reserved for positive infinity (sign=0, exp=~0, frac=0), negative infinity (sign=1, exp=~0, frac=0), and many NaN (Not a Number: exp=~0, frac≠0).

All you need to worry about: some arithmetic may cause floating point exceptions/traps, but those aren’t limited to only these “interesting” constants.


回答 3

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

通常,计算模无穷大会以浮点数形式返回自己,但分数无穷小会返回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中修复

I found a caveat that no one so far has mentioned. I don’t know if it will come up often in practical situations, but here it is for the sake of completeness.

Usually, calculating a number modulo infinity returns itself as a float, but a fraction modulo infinity returns nan (not a number). Here is an example:

>>> from fractions import Fraction
>>> from math import inf
>>> 3 % inf
3.0
>>> 3.5 % inf
3.5
>>> Fraction('1/3') % inf
nan

I filed an issue on the Python bug tracker. It can be seen at https://bugs.python.org/issue32968.

Update: this will be fixed in Python 3.8.


回答 4

非常糟糕的警告: 被零除

在一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

所以要小心!

A VERY BAD CAVEAT : Division by Zero

in a 1/x fraction, up to x = 1e-323 it is inf but when x = 1e-324 or little it throws ZeroDivisionError

>>> 1/1e-323
inf

>>> 1/1e-324
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: float division by zero

so be cautious!


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。