简体   繁体   English

Python Infinity-有什么需要注意的地方吗?

[英]Python Infinity - Any caveats?

So Python has positive and negative infinity: 因此,Python具有正负无穷大:

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? 有什么需要我注意的吗?

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. Python的实现很好地遵循了IEEE-754标准 ,您可以将其用作指导,但是它依赖于其编译所在的基础系统,因此可能会出现平台差异 Recently¹, a fix has been applied that allows "infinity" as well as "inf" , but that's of minor importance here. 最近¹,已应用了允许“无限”和“ inf”的修复程序,但这在这里意义不大。

The following sections equally well apply to any language that implements IEEE floating point arithmetic correctly, it is not specific to just Python. 以下各节同样适用于可以正确实现IEEE浮点算术的任何语言,不仅限于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 包含+inf任何数字都高于-inf
  • any number including -inf is lower than +inf 包括-inf在内的任何数字都小于+inf
  • +inf is neither higher nor lower than +inf +inf 既不高于也不低于 +inf
  • -inf is neither higher nor lower than -inf -inf既不高于也不低于-inf
  • any comparison involving NaN is false ( inf is neither higher, nor lower than NaN ) 任何涉及NaN比较都是错误的( inf既不高于也不低于NaN

Comparison for equality 平等比较

When compared for equality, +inf and +inf are equal, as are -inf and -inf . 比较相等时, +inf+inf相等, -inf-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. 这是一个争议很大的问题,可能对您有争议,但这是IEEE标准中的内容,Python的行为与此类似。

Of course, +inf is unequal to -inf and everything, including NaN itself, is unequal to NaN . 当然, +inf不等于-inf并且包括NaN本身在内的所有东西都不等于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 当乘以零(结果不确定)时,会产生NaN
  • when dividing any number (except infinity itself) by infinity, which yields 0.0 or -0.0 ². 当将任何数字(无穷大本身除外)除以无穷大时,将得出0.0-0.0
  • when dividing (including modulo) positive or negative infinity by positive or negative infinity, the result is undefined, so NaN . 当将正无穷或负无穷除以正无穷或无穷无穷时,结果是不确定的,因此NaN
  • when subtracting, the results may be surprising, but follow common math sense : 减去时,结果可能令人惊讶,但遵循常识
    • when doing inf - inf , the result is undefined: NaN ; 执行inf - inf ,结果不确定: NaN ;
    • when doing inf - -inf , the result is inf ; 当做inf - -inf时,结果是inf ;
    • when doing -inf - inf , the result is -inf ; 当做-inf - inf时,结果是-inf ;
    • when doing -inf - -inf , the result is undefined: NaN . 当做-inf - -inf ,结果是不确定的: NaN
  • when adding, it can be similarly surprising too: 添加时,同样可能令人惊讶:
    • when doing inf + inf , the result is inf ; 当做inf + inf ,结果是inf ;
    • when doing inf + -inf , the result is undefined: NaN ; 当做inf + -inf ,结果是不确定的: NaN ;
    • when doing -inf + inf , the result is undefined: NaN ; 当做-inf + inf ,结果是不确定的: NaN ;
    • when doing -inf + -inf , the result is -inf . 当做-inf + -inf ,结果是-inf
  • using math.pow , pow or ** is tricky, as it doesn't behave as it should. 使用math.powpow**很棘手,因为它的行为不正常。 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 . 当两个实数的结果太高而无法容纳双精度浮点数时(它应返回无穷大),它将引发溢出异常,但是当输入为inf-inf ,它的行为正确并返回inf0.0 When the second argument is NaN , it returns NaN , unless the first argument is 1.0 . 当第二个参数为NaN ,除非第一个参数为1.0 ,否则它将返回NaN There are more issues, not all covered in the docs . 还有更多的问题,而文档中并未涵盖所有问题。
  • math.exp suffers the same issues as math.pow . math.exp遭受同样的问题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 . 注1:作为附加的警告,如IEEE标准所定义,如果您的计算结果不足或1e308 * 10.0 ,结果将不是不足或1e308 * 10.0误差,而是正负无穷大: 1e308 * 10.0产生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 . 注2:由于任何计算NaN返回NaN任何比较NaN ,包括NaN本身是false ,你应该使用math.isnan函数来确定数字确实是NaN

Note 3: though Python supports writing float('-NaN') , the sign is ignored, because there exists no sign on NaN internally. 注意3:尽管Python支持编写float('-NaN') ,但该符号会被忽略,因为在NaN内部不存在任何符号。 If you divide -inf / +inf , the result is NaN , not -NaN (there is no such thing). 如果将-inf / +inf除以,则结果为NaN ,而不是-NaN (没有这样的东西)。

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. 注意4:请谨慎使用上述任何内容,因为Python依赖于为其编译的C或Java库,并且并非所有底层系统都能正确实现所有这些行为。 If you want to be sure, test for infinity prior to doing your calculations. 如果要确定,请在进行计算之前测试无穷大。

¹) Recently means since version 3.2 . ¹)最近是指从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 . ²)浮动点支持正和负零,因此: x / float('inf')保持其符号和-1 / float('inf')产生-0.01 / float(-inf)产生-0.01 / float('inf')产生0.0-1/ float(-inf)产生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. 此外, 0.0 == -0.0true ,如果您不希望它true ,则必须手动检查该符号。

You can still get not-a-number (NaN) values from simple arithmetic involving inf : 您仍然可以通过涉及inf简单算法获得非数字(NaN)值:

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

Note that you will normally not get an inf value through usual arithmetic calculations: 请注意,通常不会通过常规的算术计算获得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')

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. inf值被认为是具有特殊语义的非常特殊的值,因此最好立即通过异常了解OverflowError ,而不是将inf值静默注入计算中。

So does C99 . 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). 所有现代处理器使用的IEEE 754浮点表示法具有几个特殊的位模式,分别保留用于正无穷大(符号= 0,exp =〜0,frac = 0),负无穷大(符号= 1,exp =〜0,frac = 0) )和许多NaN(非数字: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. 您只需要担心的事情:某些算术运算可能会导致浮点异常/陷阱,但不仅限于这些“有趣的”常量。

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). 通常,计算模无穷大会以浮点数形式返回自己,但是分数模无穷小会返回nan (不是数字)。 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. 我在Python Bug Tracker上提出了一个问题。 It can be seen at https://bugs.python.org/issue32968 . 可以在https://bugs.python.org/issue32968上看到。

Update: this will be fixed in Python 3.8 . 更新:这将在Python 3.8中修复

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/x分数表示,直到x = 1e-323为止都是inf但是当x = 1e-324ZeroDivisionError它抛出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! 所以要小心!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM