51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Python 浮点数精度

计算机在处理浮点数时会用二进制表示,遇到无法用二进制精确表示的十进制浮点数时便会根据精确度位数进行截断,Python 也不例外。

Python 精度 {#Python-精度}

python 默认使用的是 double 精度, 浮点数在计算机中都是以二进制保存,当有无法精确表示的二进制数字时便会产生截断, 这就导致了在有限精度下,电脑为自己把精度范围外的小数"掐掉",导致结果不准确。

可以随时在 Python 环境下测试:

也就是说,如果你使用很精确的浮点数字计算的结果作为一个逻辑表达式时,可能会发生问题:

问题原理 {#问题原理}

double 用 64 个bit 位表示数据

有效精度位数是 52 位,那么当表示的小数用52bit 无法精确表示时便会截断

示例代码:

  • 输出信息第一行为 0.1 的小数部分二进制表示,可以说:
    $$
    0.1\approx(0.0001100110011001100110011001100110011001100110011001101000000000)_2
    $$

    事实上 0.1 的二进制表示是一个以 1100 为循环体的无限循环小数,到有效位 53 位时被截断,之后的数据变为了全零

  • 同理,第二行有:
    $$
    0.2\approx(0.0011001100110011001100110011001100110011001100110011010000000000)_2
    $$

    本质上就是 0.1 左移一位而已,也是 1100 的无限循环小数,在第 53 位被截断

  • 二者变成整数相加后得到 :
    $$
    100110011001100110011001100110011001100110011001100111000000000
    $$

  • 该数据除以 $2^{64}$ 得到 $0.1+0.2$ 的结果,就是 $0.30000000000000004$

以上流程基本就是 Python 内部计算 $0.1+0.2$ 时的过程,其余语言也一样,这是由无限循环小数难以精确表示导致的。

解决方案 {#解决方案}

如果有需要更高精度计算的需求,可以继续提升有效 bit 位数。

如果仍然无法达到精度要求,可以使用 Python decimal 包实现。

参考资料 {#参考资料}



文章链接:
https://www.zywvvd.com/notes/coding/python/python-precision/python-precision/

赞(5)
未经允许不得转载:工具盒子 » Python 浮点数精度