问题
大部分时候程序中要处理的都是生活中的数字(例如:金额),我们希望计算是按照十进制的得到可预测(数学教科书中的计算方式)的结果,但是float总是得到意外的结果:
In [11]: 0.3/3
Out[11]: 0.09999999999999999
In [21]: 0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1
Out[21]: 0.9999999999999999
In [23]: sum([0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1])
Out[23]: 0.9999999999999999
In [24]: 0.1+0.2
Out[24]: 0.30000000000000004
进行十进制计算
from decimal import Decimal
# 浮点数必须转为字符串传入才能保留十进制的精度
In [38]: Decimal(0.1)
Out[38]: Decimal('0.1000000000000000055511151231257827021181583404541015625')
In [39]: Decimal('0.1')
Out[39]: Decimal('0.1')
In [29]: Decimal('0.3')/3
Out[29]: Decimal('0.1')
In [28]: sum([Decimal('0.1')+Decimal('0.1')+Decimal('0.1')+Decimal('0.1')+Decimal('0.1')+Decimal('0.1')+Decimal('0.1')+Decimal('0.1')+Decimal('0.1')+Decimal('0.1')])
Out[28]: Decimal('1.0')
In [41]: Decimal(str(0.3/3))
Out[41]: Decimal('0.1')
In [42]: Decimal(str(0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1))
Out[42]: Decimal('1.0')
# 注:
In [34]: Decimal('0.10')*Decimal('0.20')
Out[34]: Decimal('0.0200')
# 后面保留了两个0,这符合教科书中的保留意义
保留小数位
# “.”后几位数字就是保留几位小数,所以 “.00”保留小数点后两位
# 第二个参数rounding为进位方式,常用如下:
# ROUND_HALF_EVEN 四舍五入
# ROUND_DOWN 不进位
# ROUND_UP 总是进位
In [18]: decimal.Decimal('231.1415267').quantize(decimal.Decimal('.00'), decimal.ROUND_HALF_EVEN)
Out[18]: Decimal('231.14')
In [19]: decimal.Decimal('231.1415267').quantize(decimal.Decimal('.000'), decimal.ROUND_HALF_EVEN)
Out[19]: Decimal('231.142')