为什么 python 会对这些比较感到困惑?

Why does python get confused by these comparisons?

如果我 运行 这段代码在 Python 3.8.6 我得到输出 False:

(((3980 - 91 + 1)/(3980)) * ((1 / 3980)**(91 - 1))) > (((3981 - 91 + 1)/(3981)) * ((1 / 3981)**(91 - 1)))

但是,if I run this in WolframAlpha它returnsTrue

我猜这是由于浮点数不精确造成的。但为什么它恰恰发生在这里?在我为以下函数测试的 sz 的 1200 万个组合中,这种情况只发生了两次。 z = 91s = 3980z = 92s = 3457.

(((s - z + 1)/(s)) * ((1 / s)**(z - 1))) > ((((s+1) - z + 1)/(s+1)) * ((1 / (s+1))**(z - 1)))

另外,在你的解释器中试试这些:

  1. (((3458 - 92 + 1)/(3458)) * ((1 / 3458)**(92 - 1))) > (((3459 - 92 + 1)/(3459)) * ((1 / 3459)**(92 - 1)))
  2. (((3457 - 92 + 1)/(3457)) * ((1 / 3457)**(92 - 1))) > (((3458 - 92 + 1)/(3458)) * ((1 / 3458)**(92 - 1)))
  3. (((3456 - 92 + 1)/(3456)) * ((1 / 3456)**(92 - 1))) > (((3457 - 92 + 1)/(3457)) * ((1 / 3457)**(92 - 1)))

他们给出了这些结果:

  1. True
  2. False
  3. True

为什么模式 True False True 只发生在这些输入上?保持 z 不变,没有其他值 s returns False.

舍入错误。如果您想准确了解,请阅读 IEEE 754 规范。您的数字非常小,处于次正常范围内,并且在您的示例中具有 5-10 位的精度。正常范围内的浮点数具有 53 位精度。


如果您使用 float.hex() 查看这两个值,它会显示它们的确切二进制表示形式:

>>> (((3980 - 91 + 1)/(3980)) * ((1 / 3980)**(91 - 1))).hex()
'0x0.0p+0'
>>> (((3981 - 91 + 1)/(3981)) * ((1 / 3981)**(91 - 1))).hex()
'0x0.0p+0'

它们在 IEEE 754 float64 精度下都非常小,它们都四舍五入为零。如果事实上最后一项是 really small:

>>> ((1/3981)**89).hex()
'0x0.0000000000327p-1022'

Mark Tolonen 回答了您的问题,如果您需要更精确的信息,请使用 fractions:

>>> from fractions import Fraction
>>> (Fraction(3980 - 91 + 1, 3980) * Fraction(1, 3980) ** (91 - 1)) > (Fraction(3981 - 91 + 1, 3981) * Fraction(1, 3981) ** (91 - 1))
True