繁体   English   中英

Python乘法失去浮点精度

[英]Python multiplication losing floating point precision

我最近在处理浮点数,我意识到浮点数出乎我的意料。 这是一个例子

a = 0.1
print(f"{a:0.20f}")
#'0.10000000000000000555'
b = a * 10
print(f"{b:0.20f}")
#'1.00000000000000000000'

我希望最后一次打印输出1.00000000000000005551 (即 1 后跟数字 1 到 21 of 0.1 )。

我很好奇的是为什么当乘以 10 时浮点误差会消失。算术的正常规则表明浮点误差会被传播,但这实际上并没有发生。 为什么会发生这种情况? 有没有办法避免它?

的10和0.1000000000000000055511151231257827021181583404541015625确切实数算术乘积,0.1 IEEE 754的64位二进制表示,是1.000000000000000055511151231257827021181583404541015625。

它不能完全代表。 它由 1.0 和 1.00000000000000022204460492503130808472633336181640625 括起来

它更接近 1.0,因此这是乘法的舍入到最接近的结果。

我使用一个简短的 Java 程序计算了这些数字:

import java.math.BigDecimal;

public strictfp class Test {
    public static void main(String[] args) {
        BigDecimal rawTenth = new BigDecimal(0.1);
        BigDecimal realProduct = rawTenth.multiply(BigDecimal.TEN);
        System.out.println(realProduct);
        System.out.println(new BigDecimal(Math.nextUp(1.0)));
    }
}

输出:

1.0000000000000000555111512312578270211815834045410156250
1.0000000000000002220446049250313080847263336181640625

这个答案显示了如何确定将 1/10 转换为浮点数并乘以 10 只需使用一点算术即可得出正好为 1; 无需计算大量或精确的数字。

您的 Python 实现使用常见的 IEEE-754 binary64 格式。 (Python 对应该使用哪种浮点格式的实现并不严格。)在这种格式中,数字实际上表示为应用于某个 53 位整数乘以某个 2 的幂的符号(+ 或 -)。 因为 2 -4 ≤ 1/10 < 2 -3 ,最接近 1/10 的可表示数是某个整数 M 乘以 2 -3-53 (-53 将 53 位整数缩放到 ½ 和 1 之间,而 -3 将其缩放到 2 -4和 2 -3 之间。)让我们称其为可表示数 x。

然后我们有 x = M•2 −56 = 1/10 + e,其中 e 是当我们将 1/10 舍入到最接近的可表示值时发生的一些舍入误差。 由于我们四舍五入到最接近的可表示值,|e| ≤ ½•2 −56 = 2 −57

要准确找出 e 是什么,请将 1/10 乘以 2 56 WolframAlpha告诉我们它是 7205759403792793+3/5。 为了获得最接近的可表示值,我们应该向上取整,因此 M = 7205759403792794 和 e = 2/5 • 2 −56 虽然我用 WolframAlpha 来说明这一点,但我们不需要 M,我们可以通过观察两个模 10 的幂的模式找到 e:2 1 →2, 2 2 →4, 2 3 →8, 2 4 →6, 2 5 →2, 2 6 →4,所以模式以4为循环重复,56模4为0,所以2 56模10与2 4 , 6有相同的余数,所以分数是6/10 = 3/5。 我们知道应该四舍五入到最接近的整数 1,所以 e = 2/5 • 2 −56

所以 x = M•2 −56 = 1/10 + 2/5•2 −56

现在我们可以计算出用浮点算法计算 10•x 的结果。 结果就像我们首先用实数算术计算 10•x 然后四舍五入到最接近的可表示值。 在实数算术中,10•x = 10•(1/10 + 2/5•2 −56 ) = 1 + 10•2/5•2 −56 = 1 + 4•2 −56 = 1 + 2 − 54 . 两个相邻的可表示值是 1 和 1 + 2 -52 ,并且 1 + 2 -54比 1 + 2 -52更接近于 1。 所以结果是1。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM