眾所周知在前端開(kāi)發(fā)中冕臭,存在精度丟失問(wèn)題,既經(jīng)典問(wèn)題
let a = 0.1
let b = 0.2
console.log(a + b == 0.3) //返回false
首先,我們要站在計(jì)算機(jī)的角度思考 0.1 + 0.2 這個(gè)看似小兒科的問(wèn)題摊趾。我們知道,能被計(jì)算機(jī)讀懂的是二進(jìn)制游两,而不是十進(jìn)制砾层,所以我們先把 0.1 和 0.2 轉(zhuǎn)換成二進(jìn)制看看:
0.1 => 0.0001 1001 1001 1001…(無(wú)限循環(huán))
0.2 => 0.0011 0011 0011 0011…(無(wú)限循環(huán))
上面我們發(fā)現(xiàn)0.1和0.2轉(zhuǎn)化為二進(jìn)制之后,變成了一個(gè)無(wú)限循環(huán)的數(shù)字贱案,這在現(xiàn)實(shí)生活中肛炮,無(wú)限循環(huán)我們可以理解,但計(jì)算機(jī)是不允許無(wú)限循環(huán)的,對(duì)于無(wú)限循環(huán)的小數(shù)侨糟,計(jì)算機(jī)會(huì)進(jìn)行舍入處理碍扔。進(jìn)行雙精度浮點(diǎn)數(shù)的小數(shù)部分最多支持 52 位,所以兩者相加之后得到這么一串 0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 秕重,因浮點(diǎn)數(shù)小數(shù)位的限制而截?cái)嗟亩M(jìn)制數(shù)字不同,這時(shí)候,我們?cè)侔阉D(zhuǎn)換為十進(jìn)制悲幅,就成了 0.30000000000000004套鹅。
解決方法:
// 解決js加法精度缺失問(wèn)題
add(arg1, arg2) {
arg1 = arg1.toString(), arg2 = arg2.toString();
var arg1Arr = arg1.split("."), arg2Arr = arg2.split("."), d1 = arg1Arr.length == 2 ? arg1Arr[1] : "", d2 = arg2Arr.length == 2 ? arg2Arr[1] : "";
var maxLen = Math.max(d1.length, d2.length);
var m = Math.pow(10, maxLen);
var result = Number(((arg1 * m + arg2 * m) / m).toFixed(maxLen));
var d = arguments[2];
return typeof d === "number" ? Number((result).toFixed(d)) : result;
}
//說(shuō)明:javascript的乘法結(jié)果會(huì)有誤差,在兩個(gè)浮點(diǎn)數(shù)相乘的時(shí)候會(huì)比較明顯汰具。這個(gè)函數(shù)返回較為精確的乘法結(jié)果卓鹿。
//調(diào)用:accMul(arg1,arg2)
//返回值:arg1乘以 arg2的精確結(jié)果
function accMul(arg1,arg2){
var m=0,s1=arg1.toString(),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);
}
// 給Number類型增加一個(gè)mul方法,調(diào)用起來(lái)更加方便留荔。
Number.prototype.mul = function (arg){
return accMul(arg, this);
}