前言
为什么要写这一篇老生常谈的是文章呢?因为我在实际项目开发中确实被这个问题坑的一脸懵逼。踩坑,说实在的还是挺开心的,至少证明着自己哪里还存在不足,然后以此为铺垫,叙文记之
为什么会出现这种问题?
计算机的二进制实现和位数限制有些数无法有限表示。就像一些无理数不能有限表示,如 圆周率 3.1415926…,1.3333… 等。JS 遵循IEEE 754规范,采用双精度存储(double precision),占用 64 bit。细节部分我就不具体阐述了,感兴趣的同学可自行百度了解,我在这里简单的记录一下我当时遇到的错误场景和解决方法。
精度缺失例子🌰
因为我们公司是做支付的,所以难免会涉及到金额的计算,当时是这么一个场景,需要计算一个用户的付款金额加上小费金额,最后得出该订单的总金额
初步一看,好像没多大的问题...窃喜.gif;想象是美好的,但现实是残酷的,在某一天,各种订单的错误信息铺面而来,商家的投诉也日益增加,我开始了bug排查之旅,此处省略排查步骤1万字...,在一次偶然的排雷过程中,我拿到这么一组数据,看到了其中的端倪;
当时看到这个情况我是震惊的,这是什么情况,为什么会出现这种情况,各种黑人问号脸;然后在我合理的运用搜索引擎之后,才知道原来这是js这门语言设计时的缺陷
// 比如一个很经典的案例
var a = 0.1;
var b = 0.2;
console.log(a+b) ; // 0.30000000000000004
解决方案
运用BigNumber.js去解决
既然问题出现了,那我们就得着手去处理这个问题,为什么没有自己去写函数方法去解决这个问题呢?我是觉得BigNumber.js这个js库已经足够成熟,再加上我自身的能力原因,所以我就直接引用该js库了;
解决方案大致如下
npm install --save bignumber.js=> 先安装一波import {BigNumber} from 'bignumber.js'=> import 引用- 在具体的业务场景中合理使用
简单常用的计算方法:
- 加:
plus
// 原js计算 0.2 + 0.1 = 0.30000000000000004
var num = new BigNumber(0.2);
var result = num.plus(0.1);
console.log(num); // 0.2
console.log(result); // 0.3
- 减:
minus
// 原js计算 0.3 - 0.1 = 0.19999999999999998
var num = new BigNumber(0.3);
var result = num.minus(0.1);
console.log(num); // 0.3
console.log(result); // 0.2
- 乘:
multipliedBy
// 原js计算 1.13 * 100 = 112.999999999999
var num = new BigNumber(1.13);
var result = num.multipliedBy(100);
console.log(num); // 1.13
console.log(result); // 113
- 除:
modulodividedBy
// 原js计算 1 % 0.9 = 0.09999999999999998
var num = new BigNumber(1);
var result = num.modulo(0.9);
console.log(num); // 1
console.log(result); // 0.1