因为计算机采用二进制,无法精确的表达浮点数
python 中 用 8字节64位存储空间分配了52位来存储浮点数的有效数字,11位存储指数,1位存储正负号
以下是4字节32为存储的模型
二进制的表示值表达浮点数是(-1)^sign × (1+0.Mantissa) × 2^(Expoment-127)其中127是单精度浮点数的偏移量
而Mantissa最多保留23位,所以在进行累加运算,如果二者指数位相差过大,将会导致数值较小的一方超过23位的尾数全部丢失,造成误差, 52位同理
另一方面,由于有的数据需要保留位数,细微的误差可能导致进位错误
例如:
c = 0.005
a = 0
for i in range(20):
a += c
f = float('%.2f' % a)
if f == a or i % 2 == 1:
pass
else:
print(f, a)
"""
结果
0.01 0.005
0.01 0.015
0.03 0.025
0.04 0.035
0.04 0.045
0.05 0.05499999999999999
0.06 0.06499999999999999
0.07 0.075
0.09 0.085
0.1 0.09500000000000001
"""
可以看到当循环执行第3次的时候,运算结果为0.0149999999999999, 此时真实值应为0.015
保留两位应为0.02, 但是由于小数点后第三位为4, 所以输出结果为0.01, 尽管浮点数产生的误差可以忽略不记,但保留小数点的操作,导致误差被放大到无法忽略的程度,尤其是在财务方面,对数据敏感的行业中,这种误差是不可忽略的
如何确保数据正确呢?
而如果要保证数据的正确性,一般采用两种方法:
方法一: 采用四舍六入五成双的原则
当不需要保留浮点数后面的位数时,可以采用round()
在python3 中,ruand()函数实际上采用的是,值被舍入到接近10的负ndigits次幂的倍数,如果与两个倍数的距离相等,则选择偶数,那么round取整的情况下,就会采用四舍六入五成双的原则
print(round(2.5))
print(round(3.5))
print(round(4.5))
print(round(5.5))
print(round(6.5))
"""
2
4
4
6
6
"""
运行结果永远是偶数
但是在保留小数点的情况下,round并不实行这一原则
print(r