js四舍五入的bug和方法

简单来说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"
 
posted @ 2015-12-31 11:54  TomG  阅读(8348)  评论(0编辑  收藏  举报