Javascript浮點數運算及比較代碼收集整理

如下代碼轉自:http://segmentfault.com/a/1190000000324193javascript

浮點數加法:java

/**
 ** 加法函數,用來獲得精確的加法結果
 ** 說明:javascript的加法結果會有偏差,在兩個浮點數相加的時候會比較明顯。這個函數返回較爲精確的加法結果。
 ** 調用:accAdd(arg1,arg2)
 ** 返回值:arg1加上arg2的精確結果
 **/
function accAdd(arg1, arg2) {    
    var r1, r2, m, c;    
    try {
        r1 = arg1.toString().split(".")[1].length;
    } catch (e) {
        r1 = 0;
    }    
    try {
        r2 = arg2.toString().split(".")[1].length;
    } catch (e) {
        r2 = 0;
    }
    c = Math.abs(r1 - r2);
    m = Math.pow(10, Math.max(r1, r2));    
    if (c > 0) {        
        var cm = Math.pow(10, c);        
        if (r1 > r2) {
            arg1 = Number(arg1.toString().replace(".", ""));
            arg2 = Number(arg2.toString().replace(".", "")) * cm;
        } else {
            arg1 = Number(arg1.toString().replace(".", "")) * cm;
            arg2 = Number(arg2.toString().replace(".", ""));
        }
    } else {
        arg1 = Number(arg1.toString().replace(".", ""));
        arg2 = Number(arg2.toString().replace(".", ""));
    }    
    return (arg1 + arg2) / m;
}

//給Number類型增長一個add方法,調用起來更加方便。
Number.prototype.add = function (arg) {    
    return accAdd(arg, this);
};

浮點數減法:git

/**
 ** 減法函數,用來獲得精確的減法結果
 ** 說明:javascript的減法結果會有偏差,在兩個浮點數相減的時候會比較明顯。這個函數返回較爲精確的減法結果。
 ** 調用:accSub(arg1,arg2)
 ** 返回值:arg1加上arg2的精確結果
 **/
function 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)); //last modify by deeka //動態控制精度長度
    n = (r1 >= r2) ? r1 : r2;
    return ((arg1 * m - arg2 * m) / m).toFixed(n);
}

// 給Number類型增長一個mul方法,調用起來更加方便。
Number.prototype.sub = function (arg) {
    return accMul(arg, this);
};

浮點數乘法:shell

/**
 ** 乘法函數,用來獲得精確的乘法結果
 ** 說明:javascript的乘法結果會有偏差,在兩個浮點數相乘的時候會比較明顯。這個函數返回較爲精確的乘法結果。
 ** 調用:accMul(arg1,arg2)
 ** 返回值:arg1乘以 arg2的精確結果
 **/
function 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) {
    }
    return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
}

// 給Number類型增長一個mul方法,調用起來更加方便。
Number.prototype.mul = function (arg) {
    return accMul(arg, this);
};

浮點數除法:segmentfault

/** 
 ** 除法函數,用來獲得精確的除法結果
 ** 說明:javascript的除法結果會有偏差,在兩個浮點數相除的時候會比較明顯。這個函數返回較爲精確的除法結果。
 ** 調用:accDiv(arg1,arg2)
 ** 返回值:arg1除以arg2的精確結果
 **/
function 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) {
    }
    with (Math) {
        r1 = Number(arg1.toString().replace(".", ""));
        r2 = Number(arg2.toString().replace(".", ""));
        return (r1 / r2) * pow(10, t2 - t1);
    }
}

//給Number類型增長一個div方法,調用起來更加方便。
Number.prototype.div = function (arg) {
    return accDiv(this, arg);
};


如下內容來自於:http://madscript.com/javascript/javscript-float-number-compute-problem/函數

分析
工具

JavaScript 只有一種數字類型 Number ,並且在Javascript中全部的數字都是以IEEE-754標準格式表示的。 浮點數的精度問題不是JavaScript特有的,由於有些小數以二進制表示位數是無窮的:測試

十進制           二進制
0.1              0.0001 1001 1001 1001 ...
0.2              0.0011 0011 0011 0011 ...
0.3              0.0100 1100 1100 1100 ...
0.4              0.0110 0110 0110 0110 ...
0.5              0.1
0.6              0.1001 1001 1001 1001 ...

因此好比 1.1 ,其程序實際上沒法真正的表示 ‘1.1’,而只能作到必定程度上的準確,這是沒法避免的精度丟失:this

1.09999999999999999

在JavaScript中問題還要複雜些,這裏只給一些在Chrome中測試數據:spa

輸入               輸出
1.0-0.9 == 0.1     False
1.0-0.8 == 0.2     False
1.0-0.7 == 0.3     False
1.0-0.6 == 0.4     True
1.0-0.5 == 0.5     True
1.0-0.4 == 0.6     True
1.0-0.3 == 0.7     True
1.0-0.2 == 0.8     True
1.0-0.1 == 0.9     True

目前比較流行的方法:在判斷浮點運算結果前對計算結果進行精度縮小,由於在精度縮小的過程總會自動四捨五入

(1.0-0.9).toFixed(digits)                      // toFixed() 精度參數須在 0 與20 之間
parseFloat((1.0-0.9).toFixed(10)) === 0.1      // 結果爲True
parseFloat((1.0-0.8).toFixed(10)) === 0.2      // 結果爲True
parseFloat((1.0-0.7).toFixed(10)) === 0.3      // 結果爲True
parseFloat((11.0-11.8).toFixed(10)) === -0.8   // 結果爲True

對以上思路經行封裝

// 經過isEqual工具方法判斷數值是否相等
function isEqual(number1, number2, digits){
    digits = digits == undefined? 10: digits; // 默認精度爲10
    return number1.toFixed(digits) === number2.toFixed(digits);
}

isEqual(1.0-0.7, 0.3);  // return true

// 原生擴展方式,更喜歡面向對象的風格
Number.prototype.isEqual = function(number, digits){
    digits = digits == undefined? 10: digits; // 默認精度爲10
    return this.toFixed(digits) === number.toFixed(digits);
}

(1.0-0.7).isEqual(0.3); // return true
相關文章
相關標籤/搜索