原文鏈接:js加減乘除精確函數(shù)
js加減乘除精確原因和解決函數(shù)百度很多地方都能百度到,下面我把百度到的精華部分總結(jié)一下
先說說不精準原因:
拿0.1+0.2=0.30000000000000004進行舉例
首先,我們要站在計算機的角度思考 0.1 + 0.2 這個看似小兒科的問題妓灌。我們知道饱狂,能被計算機讀懂的是二進制章母,而不是十進制茫舶,所以我們先把 0.1 和 0.2 轉(zhuǎn)換成二進制看看:
0.1 => 0.0001 1001 1001 1001…(無限循環(huán))
0.2 => 0.0011 0011 0011 0011…(無限循環(huán))
上面我們發(fā)現(xiàn)0.1和0.2轉(zhuǎn)化為二進制之后雾袱,變成了一個無限循環(huán)的數(shù)字恤筛,這在現(xiàn)實生活中,無限循環(huán)我們可以理解芹橡,但計算機是不允許無限循環(huán)的毒坛,對于無限循環(huán)的小數(shù),計算機會進行舍入處理。進行雙精度浮點數(shù)的小數(shù)部分最多支持 52 位煎殷,所以兩者相加之后得到這么一串 0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 屯伞,因浮點數(shù)小數(shù)位的限制而截斷的二進制數(shù)字,這時候豪直,我們再把它轉(zhuǎn)換為十進制劣摇,就成了 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
},
// 浮點型減法末融,被減數(shù),減數(shù)
NumberSub(arg1,arg2){
? ? return this.NumberAdd(arg1,-arg2);
},
// 被除數(shù)暇韧,除數(shù)勾习, 保留的小數(shù)點后的位數(shù)
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(".",""))
? ? //獲取小數(shù)點后的計算值
? ? 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);
}