最近在做小程序的一個(gè)項(xiàng)目 老大要求所有的計(jì)算出來(lái)的金錢(qián)數(shù)字都要保留兩位小數(shù)點(diǎn),自然而然想到了js的toFixed() 方法,然而既然寫(xiě)了這個(gè)文章結(jié)局肯定不想而知......閑言少敘 上代碼
還是再說(shuō)幾句吧 好歹描述一下 業(yè)務(wù)場(chǎng)景 復(fù)現(xiàn)一下過(guò)程, 過(guò)程是這個(gè)樣子滴
后臺(tái)設(shè)置了折扣的金額 8.745折 我這個(gè)時(shí)候訂單的金額是10RMB 結(jié)果就是
let discount = 8.745; // 優(yōu)惠折扣
let money = 10;// 訂單金額
let price = discount/10*10; // 實(shí)際支付金額
console.log(price) // 實(shí)際支付的金額 8.745RMB
/***需求 (保留兩位小數(shù))***/
// 最開(kāi)始的天真想法
let price = (discount/10*10).toFixed(2)
console.log(price) // 8.74
傳到后臺(tái)發(fā)現(xiàn)后臺(tái)校驗(yàn)的金額和前臺(tái)傳的對(duì)不上......尷尬的一比 然后開(kāi)始一頓筆算,和后臺(tái)對(duì)結(jié)果,后來(lái)發(fā)現(xiàn)了問(wèn)題 后臺(tái)的結(jié)果是 8.75 前臺(tái)是8.74 差了一分錢(qián),發(fā)現(xiàn)前臺(tái)計(jì)算出來(lái)的結(jié)果保留兩位小數(shù)之后的值沒(méi)有四舍五入 ,可是我又在想 toFixed() 是四舍五入的啊 為此 去測(cè)試了一下
(8.755).toFixed(2) // 8.76
(8.745).toFixed(2) // 8.74
(8.746).toFixed(2) // 8.75
得出來(lái)的解困就是這樣 在3為小數(shù)的情況下
第二位小數(shù)小于5 第三位小數(shù)<=5 結(jié)果是不四舍五入的
這就尷尬了?。?br> 后來(lái)弄明白了是js計(jì)算的bug,js計(jì)算浮點(diǎn)數(shù)精度丟失的問(wèn)題 網(wǎng)上的庫(kù)解決這個(gè)一搜一大堆,但是咱們的需求是保留兩位小數(shù)啊 所以結(jié)合一下...
接下來(lái)就說(shuō)一下小老弟的解決辦法
function accDiv(arg1,arg2){
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){}
with(Math){
r1=Number(arg1.toString().replace(".",""))
r2=Number(arg2.toString().replace(".",""))
return accMul((r1/r2),pow(10,t2-t1));
}
}
// 乘法
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)
}
/**
以上是網(wǎng)上copy出來(lái)的
以下是我的
**/
function toFixedTwo(n){
if(!isNaN(n)){
console.error("Error:n not is Number")
return false
}
return (Math.round(accMul(n,100))/100).toFixed(2)
}
也算是歷經(jīng)磨難解決了吧!
在js浮點(diǎn)數(shù)計(jì)算精度丟失問(wèn)題導(dǎo)致結(jié)果異常和不準(zhǔn)確 也是坑了我好幾次了
ps:題外話 四月不減肥 五月徒傷悲 減肥開(kāi)始了?。?/p>