python和js小数计算精度问题处理

python和js小数计算精度问题处理

问题举例

数字计算由于数据结构底层问题,导致会某些情况下存在精度丢失问题,JavaScript也存在同类问题,可以使用decimal.js库,用法与python相似

python和js小数计算精度问题处理

In [5]: 0.1+0.1+0.1 Out[5]: 0.30000000000000004 In [13]: 0.1*3 Out[13]: 0.30000000000000004

解决方法

使用python内建库decimal可以进行准确的计算

python和js小数计算精度问题处理

# 错误用法: In [15]: decimal.Decimal(0.1) * 3 Out[15]: Decimal('0.3000000000000000166533453694') In [18]: decimal.Decimal(str(0.1 * 3)) Out[18]: Decimal('0.30000000000000004') # 正确用法: In [20]: decimal.Decimal('0.1') * 3 Out[20]: Decimal('0.3') In [21]: decimal.Decimal('0.1') * decimal.Decimal('3') Out[21]: Decimal('0.3') # 错误用法: In [23]: decimal.Decimal(0.1) + decimal.Decimal(0.1)  + decimal.Decimal(0.1) Out[23]: Decimal('0.3000000000000000166533453694') # 正确用法: In [24]: decimal.Decimal(str(0.1)) + decimal.Decimal(str(0.1))  + decimal.Decimal(str(0.1)) Out[24]: Decimal('0.3')

注意:小数计算时必须先转换为Decimal类型,且必须先转为为字符串传参,否则使用float类型传入的Decimal数已经是丢失精度,将失去使用Decimal的作用

精度和进位

quantize()方法可实现保留多少位小数操作,第一个参数为保留多少位,比如’0’不保留小数,'0.00’保留两位小数

python和js小数计算精度问题处理

# 四舍五入: In [43]: decimal.Decimal(123.214).quantize(decimal.Decimal('.00'), decimal.ROUND_HALF_UP) Out[43]: Decimal('123.21') In [44]: decimal.Decimal(123.215).quantize(decimal.Decimal('.00'), decimal.ROUND_HALF_UP) Out[44]: Decimal('123.22') # 始终不进位 In [45]: decimal.Decimal(123.214).quantize(decimal.Decimal('.00'), decimal.ROUND_DOWN) Out[45]: Decimal('123.21') In [46]: decimal.Decimal(123.215).quantize(decimal.Decimal('.00'), decimal.ROUND_DOWN) Out[46]: Decimal('123.21') # 始终进位 In [47]: decimal.Decimal(123.214).quantize(decimal.Decimal('.00'), decimal.ROUND_UP) Out[47]: Decimal('123.22') In [48]: decimal.Decimal(123.215).quantize(decimal.Decimal('.00'), decimal.ROUND_UP) Out[48]: Decimal('123.22')

常用进位方式:

进位标志 描述
decimal.ROUND_HALF_EVEN 默认值,有些情况下和四舍五入效果一样,但不完全一样,一般还是使用下面四舍五入方法
decimal.ROUND_HALF_UP 四舍五入
decimal.ROUND_UP 始终进位
decimal.ROUND_DOWN 始终不进位

服务推荐