问题来源:
想把一个‘17.99’的字符串转化成字符串1799,于是用了下面的方法:
real_price=str(int(float(real_price_obj.text.strip('¥')) * 100))#real_price_obj.text='¥17.99'
预期:real_price=‘1799’
实际:real_price=‘1798’
下面说明原因:
首先做一个实验:
x = 0.0
for i in range(10):
x += 0.1
print(x)
========================打印结果
0.1
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
0.9999999999999999
即:为什么有几行的输出看起来不对?
因为 Python 中使用双精度浮点数来存储小数。在 Python 使用的 IEEE 754 标准(52M/11E/1S)中,8字节64位存储空间分配了52位来存储浮点数的有效数字,11位存储指数,1位存储正负号,即这是一种二进制版的科学计数法格式。虽然52位有效数字看起来很多,但麻烦之处在于,二进制小数在表示有理数时极易遇到无限循环的问题。其中很多在十进制小数中是有限的,比如十进制的 1/10,在十进制中可以简单写为 0.1 ,但在二进制中,他得写成:0.0001100110011001100110011001100110011001100110011001…..(后面全是 1001 循环)。因为浮点数只有52位有效数字,从第53位开始,就舍入了。这样就造成了标题里提到的”浮点数精度损失“问题。 舍入(round)的规则为“0 舍 1 入”,所以有时候会稍大一点有时候会稍小一点。
>>> x=0.0
>>> for i in range(10):
... x+=0.1
... print(round(x,1))
...
==================结果
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1.0
而为了回应人们在某些状况下对这个精度问题难以忍受的心情,Python 提供了另一种数字类型——Decimal 。他并不是内建的,因此使用它的时候需要 import decimal 模块,并使用 decimal.Decimal() 来存储精确的数字。这里需要注意的是:使用非整数参数时要记得传入一个字符串而不是浮点数,否则在作为参数的时候,这个值可能就已经是不精确的了:
Decimal(0.1) == Decimal('0.1')
False
总结:
工程项目中还是用Decimal比较靠谱;想用float的话,需要配合使用round()解决精度问题~
网友评论