原文链接:js加减乘除精确函数
js加减乘除精确原因和解决函数百度很多地方都能百度到,下面我把百度到的精华部分总结一下
先说说不精准原因:
拿0.1+0.2=0.30000000000000004进行举例
首先,我们要站在计算机的角度思考 0.1 + 0.2 这个看似小儿科的问题。我们知道,能被计算机读懂的是二进制,而不是十进制,所以我们先把 0.1 和 0.2 转换成二进制看看:
0.1 => 0.0001 1001 1001 1001…(无限循环)
0.2 => 0.0011 0011 0011 0011…(无限循环)
上面我们发现0.1和0.2转化为二进制之后,变成了一个无限循环的数字,这在现实生活中,无限循环我们可以理解,但计算机是不允许无限循环的,对于无限循环的小数,计算机会进行舍入处理。进行双精度浮点数的小数部分最多支持 52 位,所以两者相加之后得到这么一串 0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 ,因浮点数小数位的限制而截断的二进制数字,这时候,我们再把它转换为十进制,就成了 0.30000000000000004。
我相信上面这部分文字解释得很清楚,下面直接上精确计算代码
// 浮点型乘法
NumberMul(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);
},
// 浮点型加法
NumberAdd(arg1,arg2){
var r1,r2,m;
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))
return (arg1*m+arg2*m)/m
},
// 浮点型减法,被减数,减数
NumberSub(arg1,arg2){
return this.NumberAdd(arg1,-arg2);
},
// 被除数,除数, 保留的小数点后的位数
NumberDiv(arg1,arg2,digit){
var t1=0,t2=0,r1,r2;
try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0}
try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0}
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);
}