JavaScript中的toFixed()

2021-12-29  本文已影响0人  如雨随行2020

@[toc]

一、用法

设置浮点数的精度,采用的四舍五入。

var a = 1.333;
console.log('a:', a.toFixed(2));
//a:1.33

二、问题

toFixed还不同的浏览器实现,在IE10及以上里面是正常的四舍五入,但是别的浏览器里面就不一样了,它不是正常的四舍五入(等下重点说),比如:

var a = 1.335;
console.log(a.toFixed(2))
// IE         1.34
//chorme   1.33

官方说法是:
toFixed它是一个四舍六入五成双的诡异的方法(也叫银行家算法),"四舍六入五成双"含义:对于位数很多的近似数,当有效位数确定后,其后面多余的数字应该舍去,只保留有效数字最末一位,这种修约(舍入)规则是“四舍六入五成双”,也即“4舍6入5凑偶”这里“四”是指≤4 时舍去,"六"是指≥6时进上,"五"指的是根据5后面的数字来定,当5后有数时,舍5入1;当5后无有效数字时,需要分两种情况来讲:①5前为奇数,舍5入1;②5前为偶数,舍5不进。(0是偶数)

但是,经过测试发现,在chorme里面,并没有完全遵守这个规则。

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;
}

上一篇下一篇

猜你喜欢

热点阅读