关于js小数浮点数操纵涌现的精度题目的缘由以及解决方法

一、题目的引入

本日在看基础js文章的时刻发明了一个浮点数的精度题目,当打印小数相加的时刻有时刻会涌现数值不准确的状况,如果是在做一些须要数据精度请求较高的事情的时刻稍有不慎就会涌现题目

console.log(0.1+0.1) //0.2
console.log(0.1+0.2) //0.30000000000000004(精度最高保存到17位)

查阅材料以后,发明是因为像 0.1+0.2如许的操纵关于计算机来讲转换为二进制以后将是两个无穷轮回的数。而关于计算机而言是不允许有无穷的,举行四舍五入以后双精度浮点数保存52位,结果为0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100转为十进制就是0.30000000000000004

二、基础处理方法

【1】应用toFixed(digits)
toFixed函数在digits参数存在的状况下返回一个所给数值的定点数示意法的字符串(digits要在0-20之间,默以为0)。我们能够应用该函数限制返回数值的位数,从而到达进步精度的结果。

 var floatNum=0.1+0.2;
 console.log(floatNum);   //0.30000000000000004
 console.log(floatNum.toFixed(2)) //0.30
 
 console.log(1.35.toFixed(1)) //1.4
 console.log(1.33335.toFixed(4)); //1.3334 

在这里我们看上去是处理了题目,然则和直接举行相加一样有时刻toFixed 也会有题目

    Chrome:
    console.log(1.55.toFixed(1));// 1.6
    console.log(1.555.toFixed(2));//1.55
    console.log(1.5555.toFixed(3));//1.556

关于这个题目,MDN上函数的形貌为 “该数值在必要时举行四舍五入,另外在必要时会用 0 来添补小数部份,以便小数部份有指定的位数。”至因而怎样定义“必要”的,差别的浏览器会有差别的状况。

    IE:
    console.log(1.55.toFixed(1)); //1.6
    console.log(1.555.toFixed(2)); //1.56
    console.log(1.5555.toFixed(3)); //1.556

【2】重写toFixed函数

思绪为放大原有的数据,应用整数的整除来防止精度丧失

    function toFixed(num, s) {
        if(typeof s==='undefined'){
            return parseInt(num)+'';
        }
        if(typeof s!=='number'){
            return '请准确输入保存位数(数字)';
        }
        var times = Math.pow(10, s);
        var newNum = num * times+0.5;//加0.5是为了完成四舍五入中"入"的那0.5
        newNum = parseInt(newNum) / times;
        return newNum + ''//toFixed返回的是字符范例的数据
    }
    console.log(toFixed(1.5)) //2
    console.log(toFixed(1.55,1)) //1.6
    console.log(toFixed(1.555,2))  //1.56
    console.log(toFixed(1.5555,3)) //1.556

【3】基础运算自完成

    function getDecimalLength(num){ //猎取小数位长度
        let length=0;
        try{
            length =String(num).split('.')[1].length
        }catch(e){
            //TODO handle the exception
        }
        return length;
    }
    
    function getBeishu(num1,num2){  //猎取放大倍数
        let num1DecimalLength=getDecimalLength(num1);
        let num2DecimalLength=getDecimalLength(num2);
        let longer=Math.max(num1DecimalLength,num2DecimalLength);
        return Math.pow(10,longer);
    }
    
    
    //加减乘除算法
    function add(num1,num2){
        let beishu=getBeishu(num1,num2);
        return (num1*beishu+num2*beishu)/beishu;
    }
    
    function sub(num1,num2){
        let beishu=getBeishu(num1,num);
        return (num1*beishu-num2*beishu)/beishu;
    }
    
    function mul(num1,num2){
        let num1DecLen=getDecimalLength(num1);
        let num2DecLen=getDecimalLength(num2);
        let num1toStr=String(num1);
        let num2toStr=String(num2);
        return Number(num1toStr.replace('.',''))*Number(num2toStr.replace('.',''))/Math.pow(10,num1DecLen+num2DecLen)
    }
    
    
    function dev(num1,num2){
        let num1DecLen=getDecimalLength(num1);
        let num2DecLen=getDecimalLength(num2);
        let num1toStr=String(num1);
        let num2toStr=String(num2);
        return Number(num1toStr.replace('.',''))/Number(num2toStr.replace('.',''))/Math.pow(10,num1DecLen-num2DecLen)
    }
    原文作者:Leiemi
    原文地址: https://segmentfault.com/a/1190000018685770
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞