Python十进制-乘以零



为什么以下代码:

from decimal import Decimal
result = Decimal('0') * Decimal('0.8881783462119193534061639577')
print(result)

<返回strong>0即使

?我已经跟踪到模块中的以下代码:

if not self or not other:
ans = _dec_from_triple(resultsign, '0', resultexp)
# Fixing in case the exponent is out of bounds
ans = ans._fix(context)
return ans

代码似乎遵循十进制算术规范,该规范没有明确建议当我们乘以零时该怎么做,引用另一个标准中的"特殊数字",也没有指定当我们将整数乘以零时该怎么做:)所以小数库做的事情是明确指定:

  • 在舍入之前,通过将操作数的系数相乘计算结果的系数。
  • 结果的指数,在舍入之前,是两个操作数的指数之和。
  • 结果的符号是操作数符号的异或。

问题:如果其中一个操作数为零,需要返回系数和指数(即0E-28)是什么?在调用乘法函数时我们已经知道这个系数是什么了。为什么不直接返回0呢?

Raymond Hettinger在cpython github上给出了全面的解释:

在算术运算中,算术运算规则一节告诉我们:

操作后不删除后面的零。

有一些测试用例涵盖了乘零。下面是一些来自multiply.decTest:

-- zeros, etc.
mulx021 multiply  0      0     ->  0
mulx022 multiply  0     -0     -> -0
mulx023 multiply -0      0     -> -0
mulx024 multiply -0     -0     ->  0
mulx025 multiply -0.0   -0.0   ->  0.00
mulx026 multiply -0.0   -0.0   ->  0.00
mulx027 multiply -0.0   -0.0   ->  0.00
mulx028 multiply -0.0   -0.0   ->  0.00
mulx030 multiply  5.00   1E-3  ->  0.00500
mulx031 multiply  00.00  0.000 ->  0.00000
mulx032 multiply  00.00  0E-3  ->  0.00000     -- rhs is 0
mulx033 multiply  0E-3   00.00 ->  0.00000     -- lhs is 0
mulx034 multiply -5.00   1E-3  -> -0.00500
mulx035 multiply -00.00  0.000 -> -0.00000
mulx036 multiply -00.00  0E-3  -> -0.00000     -- rhs is 0
mulx037 multiply -0E-3   00.00 -> -0.00000     -- lhs is 0
mulx038 multiply  5.00  -1E-3  -> -0.00500
mulx039 multiply  00.00 -0.000 -> -0.00000
mulx040 multiply  00.00 -0E-3  -> -0.00000     -- rhs is 0
mulx041 multiply  0E-3  -00.00 -> -0.00000     -- lhs is 0
mulx042 multiply -5.00  -1E-3  ->  0.00500
mulx043 multiply -00.00 -0.000 ->  0.00000
mulx044 multiply -00.00 -0E-3  ->  0.00000     -- rhs is 0
mulx045 multiply -0E-3  -00.00 ->  0.00000     -- lhs is 0

这个来自示例:

mulx053 multiply 0.9 -0 -> -0.0

在Summary of Arithmetic一节中,从一个较高的层次解释了动机:

该算法被设计为十进制扩展浮点运算,直接实现了人们所学习的规则学校。在给定的工作精度下,可以得到精确的非舍入结果在可能的情况下给出(例如,0.9 ÷ 10得0.09,而不是。0.089999996),并且在大多数操作中都正确地保留了后面的零(1.23 + 1.27得到2.50,而不是2.5)。结果会怎样?超过工作精度,适用浮点规则。

更多细节见FAQ一节为什么后面的小数零很重要?