js中浮点数计算

浮点数计算(这里虽然使用的使typescript,但是js和这个差不多)

可能某些需求里面对数字要求比较严格,特别是财务,如果单元是元的花,差距也不大,但是如果单位是百万亿之类比较大数值的话,精度就很重要了

参考了这位兄弟的文章,并改写了他的代码。(他的代码中除法计算有一处问题,在Math.pow(10,t2-t1)中,如果t2小于t1的时候该值是一个小于1的小数,计算的时候可能造成精度丢失)
下面是是使用typescript写的加减乘除法

export class Calc {
    sum: Number = 0
    constructor(value: Number) {
        this.sum = value
    }
    add(arg: Number) {
        return this.accAdd(arg, this.sum)
    }
    sub(arg: Number) {
        return this.accSub(this.sum, arg)
    }
    mul(arg: Number) {
        return this.accMul(arg, this.sum)
    }
    div(arg: Number) {
        return this.accDiv(this.sum, arg)
    }
    // 加法
    accAdd(arg1, arg2) {
        var r1, r2, m;
        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));
        this.sum = (arg1 * m + arg2 * m) / m
        return this;
    }
    // 减法
    accSub(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;
        this.sum = parseFloat(((arg1 * m - arg2 * m) / m).toFixed(n));
        return this
    }
    // 乘法
    accMul(arg1, arg2) {
        var m = 0,
            s1 = arg1.toString(),
            s2 = arg2.toString();
        try {
            m += s1.split(".")[1].length;
        } catch (e) { }
        try {
            m += s2.split(".")[1].length;
        } catch (e) { }
        this.sum = Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
        return this
    }
    // 除法
    accDiv(arg1, arg2) {
        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(".", ""));
        if (t2 > t1) this.sum = (r1 / r2) * Math.pow(10, t2 - t1);
        else this.sum = this.accMul(r1 / r2, Math.pow(10, t2 - t1)).sum
        return this
    }
}
// 使用
           console.log(new Calc(0.1).add(0.2).add(0.3).sum) // 0.6
        console.log(0.1 + 0.2 + 0.3) // 0.6000000000000001
        console.log(new Calc(0.6).sub(0.2).sub(0.3).sum)// 0.1
        console.log(0.6 - 0.2 - 0.3) // 0.09999999999999998
        console.log(new Calc(0.1).mul(0.2).mul(0.3).sum) // 0.006
        console.log(0.1 * 0.2 * 0.3) // 0.006000000000000001
        console.log(new Calc(0.6).div(0.2).div(0.1).sum) // 30
        console.log(0.6 / 0.2 / 0.1) // 29.999999999999993
        console.log(new Calc(0.6).add(0.3).mul(0.2).div(0.1).sum) // 1.8
        console.log((0.6 + 0.3) * 0.2 / 0.1) // 1.7999999999999998
        console.log(new Calc(0.6).add(0.1).mul(0.2).sum) // 0.14
        console.log((0.6 + 0.1) * 0.2) // 0.13999999999999999