js加减乘除精确函数

js加减乘除精确函数

js加减乘除精确原因和解决函数百度很多地方都能百度到,下面我把百度到的精华部分总结一下

先说说不精准原因:

拿0.1+0.2=0.30000000000000004进行举例

首先,我们要站在计算机的角度思考 0.1 + 0.2 这个看似小儿科的问题。我们知道,能被计算机读懂的是二进制,而不是十进制,所以我们先把 0.1 和 0.2 转换成二进制看看:

0.1 => 0.0001 1001 1001 1001…(无限循环)
0.2 => 0.0011 0011 0011 0011…(无限循环)

上面我们发现0.1和0.2转化为二进制之后,变成了一个无限循环的数字,这在现实生活中,无限循环我们可以理解,但计算机是不允许无限循环的,对于无限循环的小数,计算机会进行舍入处理。进行双精度浮点数的小数部分最多支持 52 位,所以两者相加之后得到这么一串 0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 ,因浮点数小数位的限制而截断的二进制数字,这时候,我们再把它转换为十进制,就成了 0.30000000000000004。

我相信上面这部分文字解释得很清楚,下面直接上精确计算代码

// 浮点型乘法,to_fixed为保留几位小数
function NumberMul(arg1, arg2, to_fixed=-1) {
    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) {
    }
    let r = Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)
    if(to_fixed < 0){
        return r
    }
    return r.toFixed(to_fixed);
}


// 浮点型加法
// 需要使用精确乘法函数,不然会出现不精确情况
function NumberAdd(arg1,arg2){
    let r1,r2,m,a;
    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))
    a = Number((NumberMul(arg1,m)+NumberMul(arg2,m))/m)
    return a
}

// 浮点型减法,被减数,减数
NumberSub(arg1,arg2){
    return this.NumberAdd(arg1,-arg2);
},


// 被除数,除数, 保留的小数点后的位数
NumberDiv(arg1,arg2,digit){
    var t1=0,t2=0,r1,r2;
    try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0}
    try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0}
    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);
}
暂无评论

发送评论 编辑评论


				
上一篇
下一篇