浮点数的误差
浮点数的误差
print(0.1 + 0.1 + 0.1 == 0.3)
输出:
False
浮点数的误差问题与语言无关,本质上是二进制的存储问题造成的。
任何数据在计算机中都是以机器码存储的。
十进制的数字在计算机中是以二进制的数字存储的。
十进制的浮点数在计算机中也是以二进制的小数存储,以二进制运算。
那么,
在十进制转化为二进制存储的时候,引起截断误差。
在二进制的浮点数进行计算的时候,引起累加误差。
截断误差
十进制浮点数也不能完全表示小数,比如1/3
同样,二进制浮点数也不能完全表示无限小数或者虽然不是无限的但是无法完全存储的小数(位数超过了计算机存储浮点数的位数)。
大部分十进制小数都无法用二进制小数完全表示,一般都是用近似值存储在计算机中。
比如:0.1
的二进制近似值表示是: 0.1000000000000000055511151231257827021181583404541015625
并不是数学意义上完全的二进制表示。0.1
转换成二进制是一个无限小数。
一般情况下,计算机显示的是一个舍入值,1/10
打印结果: 0.1
即看上去精确的结果,其实在计算机中存储的是一个近似值。
而且,存在两个十进制浮点数在计算机*用一个二进制近似小数的情况。0.1
、0.10000000000000001
共用一个二进制近似小数。
python3.1之后,碰到共用情况,选择最短的十进制浮点数显示。
一般情况下,不用理会这些误差问题,但是要有浮点数存在误差的概念。在某些任务下,浮点数的误差会带来问题。
这时候可以使用能够精确表示十进制浮点数的decimal
模块,或者fractions
模块(用1/2这样的表示有理数),以及scipy的Numerical Python包。
累加误差
大数加小数,对阶过程中,必须指数位一样大,那么小的数的尾数部分就会变多,如果超出了存储的位数,就会截掉小数的超出位数,引起误差。如果多次进行运算,累加误差会越来越大。
除此之外,本身存储的浮点数就存在截断误差,在运算过程中,这个误差也会放大。也算作累加误差。
后记
对于财务、高精度计算等,一定需要考虑浮点数的误差问题,尽量减少误差。不然计算少了钱算让写代码的掏。
但也不能因为浮点数的误差问题,就去避免浮点数的使用。只要你的项目要求的误差限能够满足就好。不存在无限精度的情况。
参考资料:
python tutorial
累加误差
上一篇: 板栗可以晒吗,带你走进板栗的美味当中