python - python浮点乘法中出现残差的原因

标签 python floating-point multiplication

为什么在Python中的一些浮点乘法中会有那些奇怪的残差?

例如

>>> 50*1.1
55.00000000000001

但是

>>> 30*1.1
33.0

原因应该是 float 的二进制表示中的某个地方,但是这两个示例的具体区别在哪里?

最佳答案

(此答案假设您的 Python 实现使用 IEEE-754 二进制 64,这很常见。)

1.1转换为 float 时,结果恰好是1.100000000000000088817841970012523233890533447265625,因为这是最接近的可表示值。 (这个数字是 4953959590107546 • 2−52 — 最多 53 位的整数乘以 2 的幂。)

乘以 50 时,精确的数学结果为 55.00000000000000444089209850062616169452667236328125。这无法用 binary64 精确表示。为了使其符合binary64格式,它被四舍五入到最接近的可表示值,即55.00000000000000710542735760100185871124267578125(即7740561859543041•2−47)。

乘以30时,准确结果为33.00000000000000266453525910037569701671600341796875。它也不能用binary64 精确表示。它被四舍五入到最接近的可表示值,即 33。(下一个更高的可表示值是 33.00000000000000710542735760100185871124267578125,我们可以看到…026 更接近…000,而不是…071。)

这解释了内部结果是什么。接下来的问题是 Python 实现如何格式化输出。我不认为 Python 实现对此很严格,但很可能使用以下两种方法之一:

  • 实际上,数字会转换为一定数量的十进制数字,然后删除尾随的无意义零。将 55.00000000000000710542735760100185871124267578125 转换为小数点后 16 位数字会得到 55.00000000000001,其中没有需要删除的尾随零。将 33 转换为小数点后 16 位数字会得到 33.00000000000000,其中需要删除 15 个尾随零。 (大概您的 Python 实现总是在小数点后留下至少一个尾随零,以清楚地区分它是 float 而不是整数。)
  • 使用足够的十进制数字来唯一区分该数字与相邻的可表示值。此方法在 Java 和 JavaScript 中是必需的,但在其他编程语言中尚不常见。对于 55.00000000000000710542735760100185871124267578125,打印“55.00000000000001”可将其与相邻值 55(其格式为“55.0”)和 55.00000000000001421 区分开来08547152020037174224853515625(即“55.000000000000014”)。

关于python - python浮点乘法中出现残差的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59749534/

相关文章:

c - 大数的模乘

python - 将计数更改为字母数组,python

python - 如果我将元素放入括号中,则乘法为零(python)

python - Sci-Kit 学习 SGD 算法时出错 - "Array contains NaN or infinity"

rust - LLVM 优化器不尊重使用 Rust 内联 asm 设置非默认舍入模式?

c# - 如果不对 float 进行任何操作, float 会失去精度吗

delphi - Delphi5中浮点除零异常

python - 将多项式与 numpy.convolve 相乘返回错误结果

python - Pandas 数据框中的复杂选择

python - 取消 xmlrpc 客户端请求?