Python3 Infinity/NaN:十进制与浮点数

Python3 Infinity/NaN: Decimal vs. float

给定(Python3):

>>> float('inf') == Decimal('inf')
True 

>>> float('-inf') <= float('nan') <= float('inf')
False

>>> float('-inf') <= Decimal(1) <= float('inf')
True

为什么以下无效?我已阅读Special values

无效

>>> Decimal('-inf') <= Decimal('nan') <= Decimal('inf')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]

>>> Decimal('-inf') <= float('nan') <= Decimal('inf')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]

>>> float('-inf') <= Decimal('nan') <= float('inf')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]

来自decimal.py source code

# Note: The Decimal standard doesn't cover rich comparisons for
# Decimals.  In particular, the specification is silent on the
# subject of what should happen for a comparison involving a NaN.
# We take the following approach:
#
#   == comparisons involving a quiet NaN always return False
#   != comparisons involving a quiet NaN always return True
#   == or != comparisons involving a signaling NaN signal
#      InvalidOperation, and return False or True as above if the
#      InvalidOperation is not trapped.
#   <, >, <= and >= comparisons involving a (quiet or signaling)
#      NaN signal InvalidOperation, and return False if the
#      InvalidOperation is not trapped.
#
# This behavior is designed to conform as closely as possible to
# that specified by IEEE 754.

Special values section 你说你读到:

An attempt to compare two Decimals using any of the <, <=, > or >= operators will raise the InvalidOperation signal if either operand is a NaN, and return False if this signal is not trapped.

注意 IEEE 754 使用 NaN 作为浮点数异常值;例如你做了一些无法计算的事情,而是得到了一个异常。它是一个信号值,应该被视为一个错误,而不是用来比较其他浮点数的东西,这就是为什么在 IEEE 754 标准中它不等于其他任何东西。

此外,特殊值部分提到:

Note that the General Decimal Arithmetic specification does not specify the behavior of direct comparisons; these rules for comparisons involving a NaN were taken from the IEEE 854 standard (see Table 3 in section 5.7).

looking at IEEE 854 section 5.7我们发现:

In addition to the true/false response, an invalid operation exception (see 7.1) shall be signaled when, as indicated in the last column of Table 3, “unordered” operands are compared using one of the predicates involving “<” or “>” but not “?.” (Here the symbol “?” signifies “unordered.” )

与分类为无序的 NaN 进行比较。

默认情况下 InvalidOperation 被捕获,因此在对 Decimal('NaN') 使用 <=>= 时会引发 Python 异常。这是一个合乎逻辑的扩展; Python 有 实际 异常,因此如果您与 NaN 异常值进行比较,您可以预期会引发异常。

您可以使用 Decimal.localcontext():

来禁用陷印
>>> from decimal import localcontext, Decimal, InvalidOperation
>>> with localcontext() as ctx:
...     ctx.traps[InvalidOperation] = 0
...     Decimal('-inf') <= Decimal('nan') <= Decimal('inf')
... 
False