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

时间:2015-02-06 17:25:47

标签: python python-3.x nan infinity

鉴于(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'>]

1 个答案:

答案 0 :(得分:3)

来自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读到:

  

尝试使用任何<<=>>=运算符比较两个小数将会引发InvalidOperation信号,如果其中任一操作数为NaN,如果此信号未被捕获,则返回False

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

此外,特殊值部分提到:

  

请注意,“一般十进制算术”规范未指定直接比较的行为;这些涉及NaN的比较规则取自IEEE 854标准(参见5.7节中的表3)。

looking at IEEE 854 section 5.7我们发现:

  

除了真/假响应之外,还应发出无效操作异常(见7.1)的信号   当如表3的最后一列所示,使用其中一个谓词比较“无序”操作数时   涉及“&lt;”或“&gt;”而不是“?”(这里符号“?”表示“无序”。)

与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