簡單來說js使用原生toFixed(x)截取小數的時候會有誤差,出現在比如var o = 0.3303;o.toFixed(3);//0.330
toFixed(x)本來也是一個獲取四舍五入的截取方法,但這個bug實在不能忍,所以還是用Math.round(x)比較穩定
toFixed(x)
在js中四舍五入的函數 tofixed(n) , n為要保留的小數位數。
n為0~20,當n超過20的時候,js會出錯,這東西好像只能傳一個數字進去,字符串會爆不是一個方法
var d=10.005;
d.toFixed(2);
//"10.01"
bug
var d=13.35;
d.toFixed(1);
//13.3
Number(13.35).toFixed(1); //13.3 //what's the hell!
Number(0.055).toFixed(1); //0.1
//如果要修改這個缺陷,可以把js中的number類型的tofixed方法重寫。
round 方法
返回與給出的數值表達式最接近的整數。
math.round(number)
必選項 number 參數是要舍入到最接近整數的值。
說明
如果 number 的小數部分大於等於 0.5,返回值是大於 number 的最小整數。
否則,round 返回小於等於 number 的最大整數。
其實我們可以用一種更加簡潔的方法來解決這個問題:用Math.round方法來實現四舍五入。
比如,四舍五入一個數字並保留小數點后兩位,我們可以這么干:
Math.round(num * Math.pow(10, 2)) / Math.pow(10, 2); //num是待處理數字
當num = 10.10500時,計算上述表達式可得10.11。(正常)
當num = "10.50000"時(注意這里是字符串),計算上述表達式可得10.5。(damn it,小數點后位數不對!)
.....
當num是字符串,進行乘法操作時,進行了類型轉換,后綴零被丟棄了,導致位數不足,這個時候我們就應該進行補零:
(Math.round(num * Math.pow(10, 2)) / Math.pow(10, 2) + 0.001).toString().slice(0, -1) //加上一個小數點后多一位的數字0.001,再刪除最后一個字符即可。
//slice(0, -1) 這個是截取一個對象或者數組的方法,表示取去除符合邏輯的其他對象,這里上下文是從轉換成字符串之后的從0開始截取到倒數第一位的位置,就是把倒數第一位給干掉,因為手動加上了0.*1這個,所以要把多出來的那個1給干掉就剛好截取了
大概方法就是先剩10的n次方再除10的n次方,然后加上10的-(n+1)次方,轉成字符串正好多了一位1,再用slice方法把這個1干掉,具體邏輯驗證過了,可以直接用
綜上,修正的toFixed計算表達式如下:
(Math.round(num * Math.pow(10, fractionDigits)) / Math.pow(10, fractionDigits) + Math.pow(10, -(fractionDigits + 1))).toString().slice(0, -1)
最終得到的截取小數位數計算方法為 (Math.round(num*Math.pow(10,fractionDigits))/Math.pow(10,fractionDigits)+Math.pow(10,-(fractionDigits+1))).toString().slice(0, -1)
我的截取小數方法
var iTofixed =function(num,fractionDigits) {
return (Math.round(num*Math.pow(10,fractionDigits))/Math.pow(10,fractionDigits)+Math.pow(10,-(fractionDigits+1))).toString().slice(0, -1)
};
iTofixed('13.5000',3);
//"13.500"