javascript中toFixed()方法
以前一直以為toFixed方法就是四捨五入的,知道一個使用者反饋了金額計算的bug我才如夢初醒(虧了一毛錢),才仔細深究了下toFixed這個方法,唉,還是我不夠嚴謹啊,前車之鑑,大家勿走我的老路!
toFixed還不同的瀏覽器實現,在IE10及以上裡面是正常的四捨五入,但是別的瀏覽器裡面就不一樣了,它不是正常的四捨五入(等下重點說),比如:
var a = 1.335;
console.log(a.toFixed(2))
// IE 1.34
//chorme 1.33
其他的瀏覽器我沒去一一測試,所以如果大家用了其他瀏覽器的還是需要去實際測試一下,我這裡就說說javascript的toFixed()方法的四捨五入原理:
toFixed它是一個四捨六入五成雙的詭異的方法(也叫銀行家演算法),"四捨六入五成雙"含義:對於位數很多的近似數,當有效位數確定後,其後面多餘的數字應該捨去,只保留有效數字最末一位,這種修約(舍入)規則是“四捨六入五成雙”,也即“4舍6入5湊偶”這裡“四”是指≤4 時捨去,"六"是指≥6時進上,"五"指的是根據5後面的數字來定,當5後有數時,舍5入1;當5後無有效數字時,需要分兩種情況來講:①5前為奇數,舍5入1;②5前為偶數,舍5不進。(0是偶數)
但是,經過我的測試發現,在chorme下面(最新版),並沒有完全遵守這個規則,尤其是5的後面沒有數字的時候,不是這麼判斷的,如下:
var b = 1.335
b.toFixed(2)
"1.33"
var b = 1.345
b.toFixed(2)
"1.34"
var b = 1.355
b.toFixed(2)
"1.35"
var b = 1.365
b.toFixed(2)
"1.36"
var b = 1.375
b.toFixed(2)
"1.38"
var b = 1.385
b.toFixed(2)
"1.39"
可以發現在chorme下沒有完全去遵循這個規律,或許它有自己的演算法,但是畢竟它沒有遵循通用的銀行家演算法,所以tofixed這個方法在涉及到金錢計算的業務中還是少用,
最好別用,否則可能會出大問題!
下面再再說說我自己的做法,就是根據精確位數來取小數點後的數,然後判斷精確位是大於4還是小於等於4,上程式碼吧,不說了:
我們的業務是最多精確到分,也就是兩位小數,最少就是取整,不留小數
function moneySwitch(money, precision){//precision是需要精確的位數,如百分位就是2
var result = 0;
//先進行一個千分位的四捨五入,保證3.0999這種情況在保留一位小數的時候能是對的,這一位可以這麼做沒什麼問題
var money = parseFloat(money).toFixed(3);
try{
var int_part = money.split(".")[0], //小數點前的整數
point_num = money.split(".")[1],//取小數點後面的小數
precision_num = point_num[3-precision];
if(precision_num>4){//五入的情況
if(precision==1){
point_num = parseInt(point_num)+10+"";
if(point_num.length>3){//說明往整數位進1
int_part = parseInt(int_part)+1+"";
point_num = point_num[1]+point_num[2];
}else{
point_num = point_num[0]+point_num[1];
}
result = parseFloat(int_part+"."+point_num);
}else if(precision==2){
point_num = parseInt(point_num)+100+"";
if(point_num.length>3){//說明往整數位進1
int_part = parseInt(int_part)+1+"";
point_num = point_num[1];
}else{
point_num = point_num[0];
}
result = parseFloat(int_part+"."+point_num);
}else if(precision==3){
int_part = parseInt(int_part)+1+"";
point_num = 0;
}
result = parseFloat(int_part+"."+point_num);
}else{//四舍的情況
if(precision==1){
point_num = point_num[0]+point_num[1];
}else if(precision==2){
point_num = point_num[0];
}else if(precision==3){
point_num = 0;
}
result = parseFloat(int_part+"."+point_num);
}
}catch(e){
return parseFloat(money).toFixed(2);//如果過程中有出錯就tofixed代替為解決
}
return result;
}
---------------------
作者:show_code
來源:CSDN
原文:https://blog.csdn.net/playboyanta123/article/details/77677645
版權宣告:本文為博主原創文章,轉載請附上博文連結!