美文网首页Web前端之路让前端飞Web 前端开发
一个数字截取引发的精度问题(一)

一个数字截取引发的精度问题(一)

作者: 前端黑板报 | 来源:发表于2017-03-12 11:39 被阅读64次
    Paste_Image.png

    上周有一个“收银台”的业务需要重构,其中有一个需求:

    收益计算的结果,取小数点后两位但不进行四舍五入,若不足则补0。

    看到这个需求你应该会第一个想到:

    numberObj.toFixed([digits])
    

    因为这个方法基本可以满足这个需求。但是当看到以前同事的方法时,感觉这个方法并不能完全满足:

    /**
    * 截断小数点后几位
    * @val 数值
    * @pos 小数点后截断的位置
    */
    cutOffDecimal(val, pos) {
        // 把数字转换成字符串
        val = val.toString()
        let len = val.length
        let index = val.indexOf('.')
        let subVal = val; // 这是什么鬼?
        if (index != -1) {
          subVal = val.substring(0, index + pos +  1)
        }
        // 利用 toFixed 防止小数位达不到其位数要求
        return Number(subVal).toFixed(pos)
    }
    

    代码意思很明显,检测是否含有小数点,若有则用小数点的位置 + 精确的小数位置 + 1,因为substring最后一个位置不包括在内所以加1,
    最后用toFixed补全。

    他没有直接用toFixed,说明此方法不能直接满足。我查了一下API说明果然有猫腻:

    The number is rounded if necessary

    意思是此方法在必要时进行四舍五入,一看这个肯定不能直接满足此需求,我感觉上面代码写的也有点啰嗦,改写如下:

    export function NumberPrecision(number,prec = 0){
    
        if(typeof number != 'number' || Number.isNaN(number)){
            console.error('Must be a number but not a NaN');
            return;
        }
    
        return number.toFixed(prec + 1).slice(0,-1);
    }
    

    1.类型判断,非数字以及NaN的则报错;

    2.toFixed我没有直接取到目标位置,而是取到目标位置的下一个位置,这样就避免了该方法的四舍五入对结果造成的影响,然后再用slice截取字符串。

    关注公众号(前端黑板报),获得最新文章:

    Paste_Image.png

    加入微信群,实时交流:

    Paste_Image.png

    相关文章

      网友评论

        本文标题:一个数字截取引发的精度问题(一)

        本文链接:https://www.haomeiwen.com/subject/pfutnttx.html