我们在计算带小数的加法或者乘法除法的时候,偶尔会得到出乎预料的值,例如:
//加法
1 + 1.57 //输出: 2.5700000000000003
//减法
2 - 1.69 //输出: 0.31000000000000005
//乘法
1.219 * 10 //输出: 12.190000000000001
//除法
5.57 / 100000 //输出: 0.000055700000000000005
丢失精度的原因请查看另一篇文章:JS计算为何丢失精度
为了解决js计算丢失精度问题,我们写出以下方法:
/**
* 加法函数,避免小数丢失精度
*/
decimalsAdd() {
var args = arguments, //获取所有的参数
d = 0, //定义小数位的初始长度,默认为整数,即小数位为0
sum = 0; //定义sum来接收所有数据的和
//循环所有的参数
for (var key in args) {
//遍历所有的参数
//把数字转为字符串
var str = "" + args[key];
if (str.indexOf(".") != -1) {
//判断数字是否为小数
//获取小数位的长度
var temp = str.split(".")[1].length;
//比较此数的小数位与原小数位的长度,取小数位较长的存储到d中
d = d < temp ? temp : d;
}
}
//计算需要乘的数值
var m = Math.pow(10, d);
//遍历所有参数并相加
for (var cell in args) {
sum += args[cell] * m;
}
//返回结果
return sum / m;
},
/**
* 小数相乘,解决丢失精度问题
* @param {Number} value1
* @param {Number} value2
*/
accMul(value1, value2) {
if (value1 == 0 || value2 == 0) {
return 0;
}
let m = 0;
let v1 = value1.toString();
let v2 = value2.toString();
m += v1.split(".")[1] ? v1.split(".")[1].length : 0;
m += v2.split(".")[1] ? v2.split(".")[1].length : 0;
let _v1 = Number(v1.replace(".", ""));
let _v2 = Number(v2.replace(".", ""));
return (_v1 * _v2) / Math.pow(10, m);
},
/**
* 小数除法,解决丢失精度问题
* @param {Number} value1 除数
* @param {*} value2 被除数
*/
accDiv(value1, value2) {
if (value1 == 0) {
return 0;
}
let v1 = value1.toString();
let v2 = value2.toString();
let m1 = v1.split(".")[1] ? v1.split(".")[1].length : 0;
let m2 = v2.split(".")[1] ? v2.split(".")[1].length : 0;
let _v1 = Number(v1.replace(".", ""));
let _v2 = Number(v2.replace(".", ""));
return this.accMul(_v1 / _v2, Math.pow(10, m2 - m1));
}