JS的精确计算问题是一些做金融或一些需要计算功能的一个痛点,例如:
// 加法
0.1 + 0.2 = 0.30000000000000004
0.1 + 0.7 = 0.7999999999999999
0.2 + 0.4 = 0.6000000000000001
// 减法
0.3 - 0.2 = 0.09999999999999998
1.5 - 1.2 = 0.30000000000000004
// 乘法
0.8 * 3 = 2.4000000000000004
19.9 * 100 = 1989.9999999999998
// 除法
0.3 / 0.1 = 2.9999999999999996
0.69 / 10 = 0.06899999999999999
// 比较
0.1 + 0.2 === 0.3 // false
(0.3 - 0.2) === (0.2 - 0.1) // false
常见的解决方式使用math.js,如果在vue或react项目中(下方以vue为例)会用对应的mathjs。
官网: http://mathjs.org/
cdn地址:https://cdnjs.cloudflare.com/ajax/libs/mathjs/5.0.0/math.js
JS中的应用示例:
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/5.0.0/math.js"></script>
<script type="text/javascript">
function fn_click(p){
var a , b;
a=0.7;
b=0.1;
if(p==1){
alert(a+b);
}else if(p==2){
alert(eval("a+b"));
}else if(p==3){
math.config({
number: 'BigNumber'
});
var result = math.parser().eval(a + "+" + b)
alert(result);
}
}
</script>
</head>
<body>
<input type="button" value="0.7+0.1" onclick="fn_click(1);" />
<input type="button" value="eval(0.7+0.1)" onclick="fn_click(2);" />
<input type="button" value="mathjs(0.7+0.1)" onclick="fn_click(3);" />
</body>
</html>
在Vue中的应用示例:
但是,这样用mathjs对于比较大数字就会有不少的问题,下边我们用原生js的方式封装一个解决这样问题的方法
乘法
const NumberMul = function(arg1, arg2) {
var m = 0;
var s1 = arg1.toString();
var s2 = arg2.toString();
try {
m += s1.split(".")[1].length;
} catch (e) {}
try {
m += s2.split(".")[1].length;
} catch (e) {}
return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
}
加法
const NumberAdd = function(arg1, arg2) {
var r1, r2, m, n;
try {
r1 = arg1.toString().split(".")[1].length
} catch (e) {
r1 = 0
}
try {
r2 = arg2.toString().split(".")[1].length
} catch (e) {
r2 = 0
}
m = Math.pow(10, Math.max(r1, r2))
n = (r1 >= r2) ? r1 : r2;
return ((arg1 * m + arg2 * m) / m).toFixed(n);
}
减法
const NumberSub = function(arg1, arg2) {
var re1, re2, m, n;
try {
re1 = arg1.toString().split(".")[1].length;
} catch (e) {
re1 = 0;
}
try {
re2 = arg2.toString().split(".")[1].length;
} catch (e) {
re2 = 0;
}
m = Math.pow(10, Math.max(re1, re2));
n = (re1 >= re2) ? re1 : re2;
return ((arg1 * m - arg2 * m) / m).toFixed(n);
}
除法
// 除数,被除数, 保留的小数点后的位数
const NumberDiv = function (arg1,arg2,digit){
var t1=0,t2=0,r1,r2;
try{t1=arg1.toString().split(".")[1].length}catch(e){}
try{t2=arg2.toString().split(".")[1].length}catch(e){}
r1=Number(arg1.toString().replace(".",""))
r2=Number(arg2.toString().replace(".",""))
//获取小数点后的计算值
var result= ((r1/r2)*Math.pow(10,t2-t1)).toString()
var result2=result.split(".")[1];
result2=result2.substring(0,digit>result2.length?result2.length:digit);
return Number(result.split(".")[0]+"."+result2);
}
注意:被除数arg2 不能为0,这里就不做判断了,使用的小伙伴注意了
使用方式(以乘法方式为例)
console.log(NumberMul(0.0058,100))
如果在vue中使用的话,也可以将方法放入全局,也可以页面中单个应用
例如(以全局方式为例)
Vue.prototype.NumberMul = function(arg1, arg2) {
var m = 0;
var s1 = arg1.toString();
var s2 = arg2.toString();
try {
m += s1.split(".")[1].length;
} catch (e) {}
try {
m += s2.split(".")[1].length;
} catch (e) {}
return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
}
如果本文对你有很大用处请你点个赞吧!
本文参考:https://www.cnblogs.com/bushui/p/12150947.html