【JavaScript】浮点型计算,精度丢失问题解决

   1,开题:一个经典的面试题目:

         【JavaScript】浮点型计算,精度丢失问题解决_第1张图片

        JS本身是解释性语言,计算机在进行运算时,使用的是二进制计算,在进行计算时,存在精度丢失的问题;

  2,解决方法一:toFixed搭配parseFloat,应对一般的业务

  2.3/100000
  //=> 0.000022999999999999997
  parseFloat((2.3/100000).toFixed(16))
  //=> 0.000023

  0.0000211 * 100
  //=> 0.0021100000000000003
  parseFloat((0.0000211 * 100).toFixed(16))
  //=> 0.00211

  3,解决方式二:使用兼容的方法,进行处理 (Vue封装)

 // 乘法计算
Vue.prototype.NumberMul = function(arg1, arg2) {
    var m = 0;
    var s1 = arg1.toString();
    var s2 = arg2.toString();
    try {
        m += s1.split(".")[1].length;
    } catch (e) {}
    try {
        m += s2.split(".")[1].length;
    } catch (e) {}
 
    return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
}

// 加法计算
Vue.prototype.NumberAdd = function(arg1, arg2) {
    var r1, r2, m, n;
    try {
        r1 = arg1.toString().split(".")[1].length
    } catch (e) {
        r1 = 0
    }
    try {
        r2 = arg2.toString().split(".")[1].length
    } catch (e) { 
        r2 = 0 
    } 
    m = Math.pow(10, Math.max(r1, r2))
    n = (r1 >= r2) ? r1 : r2;
    return ((arg1 * m + arg2 * m) / m).toFixed(n);
}

// 减法计算
Vue.prototype.NumberSub = function(arg1, arg2) {
    var re1, re2, m, n;
    try {
        re1 = arg1.toString().split(".")[1].length;
    } catch (e) {
    re1 = 0;
    }
    try {
        re2 = arg2.toString().split(".")[1].length;
    } catch (e) {
        re2 = 0;
    }
    m = Math.pow(10, Math.max(re1, re2)); 
    n = (re1 >= re2) ? re1 : re2;
    return ((arg1 * m - arg2 * m) / m).toFixed(n);
}

// 除法计算
// 除数,被除数, 保留的小数点后的位数
Vue.prototype.NumberDiv = function (arg1,arg2,digit){
    var t1=0,t2=0,r1,r2;
    try{t1=arg1.toString().split(".")[1].length}catch(e){}
    try{t2=arg2.toString().split(".")[1].length}catch(e){}
    r1=Number(arg1.toString().replace(".",""))
    r2=Number(arg2.toString().replace(".",""))
    //获取小数点后的计算值
   var result= ((r1/r2)*Math.pow(10,t2-t1)).toString()
    var result2=result.split(".")[1];
    result2=result2.substring(0,digit>result2.length?result2.length:digit);
 
    return Number(result.split(".")[0]+"."+result2);
}

  4,解决方式三:重写toFixed方法

// toFixed兼容方法
Number.prototype.toFixed = function(len){
    if(len>20 || len<0){
        throw new RangeError('toFixed() digits argument must be between 0 and 20');
    }
    // .123转为0.123
    var number = Number(this);
    if (isNaN(number) || number >= Math.pow(10, 21)) {
        return number.toString();
    }
    if (typeof (len) == 'undefined' || len == 0) {
        return (Math.round(number)).toString();
    }
    var result = number.toString(),
        numberArr = result.split('.');

    if(numberArr.length<2){
        //整数的情况
        return padNum(result);
    }
    var intNum = numberArr[0], //整数部分
        deciNum = numberArr[1],//小数部分
        lastNum = deciNum.substr(len, 1);//最后一个数字
    
    if(deciNum.length == len){
        //需要截取的长度等于当前长度
        return result;
    }
    if(deciNum.length < len){
        //需要截取的长度大于当前长度 1.3.toFixed(2)
        return padNum(result)
    }
    //需要截取的长度小于当前长度,需要判断最后一位数字
    result = intNum + '.' + deciNum.substr(0, len);
    if(parseInt(lastNum, 10)>=5){
        //最后一位数字大于5,要进位
        var times = Math.pow(10, len); //需要放大的倍数
        var changedInt = Number(result.replace('.',''));//截取后转为整数
        changedInt++;//整数进位
        changedInt /= times;//整数转为小数,注:有可能还是整数
        result = padNum(changedInt+'');
    }
    return result;
    //对数字末尾加0
    function padNum(num){
        var dotPos = num.indexOf('.');
        if(dotPos === -1){
            //整数的情况
            num += '.';
            for(var i = 0;i

  5,解决方式四:使用第三方的库(number-precision,还有其它库)

   安装:npm install number-precision --save       地址:https://github.com/nefe/number-precision

   方法:

       NP.strip(num)                    // 取最近的数值
       NP.plus(num1, num2, num3, ...)   // 求和
       NP.minus(num1, num2, num3, ...)  // 相减
       NP.times(num1, num2, num3, ...)  // 求积
       NP.divide(num1, num2, num3, ...) // 相除
       NP.round(num, ratio)             // 按比例取整数

 

   参考:https://blog.csdn.net/m0_37948170/article/details/88237208

   参考:https://juejin.im/post/5aa1395c6fb9a028df223516

   参考:https://segmentfault.com/q/1010000005641246

你可能感兴趣的:(JavaScript)