简单来说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"