为什么 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
。
我猜这是由于浮点数不精确造成的。但为什么它恰恰发生在这里?在我为以下函数测试的 s
和 z
的 1200 万个组合中,这种情况只发生了两次。 z = 91
与 s = 3980
和 z = 92
与 s = 3457
.
(((s - z + 1)/(s)) * ((1 / s)**(z - 1))) > ((((s+1) - z + 1)/(s+1)) * ((1 / (s+1))**(z - 1)))
另外,在你的解释器中试试这些:
(((3458 - 92 + 1)/(3458)) * ((1 / 3458)**(92 - 1))) > (((3459 - 92 + 1)/(3459)) * ((1 / 3459)**(92 - 1)))
(((3457 - 92 + 1)/(3457)) * ((1 / 3457)**(92 - 1))) > (((3458 - 92 + 1)/(3458)) * ((1 / 3458)**(92 - 1)))
(((3456 - 92 + 1)/(3456)) * ((1 / 3456)**(92 - 1))) > (((3457 - 92 + 1)/(3457)) * ((1 / 3457)**(92 - 1)))
他们给出了这些结果:
True
False
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
如果我 运行 这段代码在 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
。
我猜这是由于浮点数不精确造成的。但为什么它恰恰发生在这里?在我为以下函数测试的 s
和 z
的 1200 万个组合中,这种情况只发生了两次。 z = 91
与 s = 3980
和 z = 92
与 s = 3457
.
(((s - z + 1)/(s)) * ((1 / s)**(z - 1))) > ((((s+1) - z + 1)/(s+1)) * ((1 / (s+1))**(z - 1)))
另外,在你的解释器中试试这些:
(((3458 - 92 + 1)/(3458)) * ((1 / 3458)**(92 - 1))) > (((3459 - 92 + 1)/(3459)) * ((1 / 3459)**(92 - 1)))
(((3457 - 92 + 1)/(3457)) * ((1 / 3457)**(92 - 1))) > (((3458 - 92 + 1)/(3458)) * ((1 / 3458)**(92 - 1)))
(((3456 - 92 + 1)/(3456)) * ((1 / 3456)**(92 - 1))) > (((3457 - 92 + 1)/(3457)) * ((1 / 3457)**(92 - 1)))
他们给出了这些结果:
True
False
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