js precise calculation

Keywords: Javascript Programming Java

Catalog

js precise calculation

var numA = 0.1; 
var numB = 0.2; 
alert( numA + numB );

0.1 + 0.2 = 0.30000000000000004.
Problem of calculation accuracy error (related to binary).

Almost all programming languages have similar precision errors for the four-way operation of floating-point numbers, except that methods have been encapsulated in C++/C#/Java to avoid accuracy problems, whereas JavaScript As a weak language, there is no strict data type for floating-point numbers in the design, so the problem of accuracy error is particularly prominent.
Let's first convert 0.1 and 0.2 to binary and see:
0.1 => 0.0001 1001 1001 1001...(infinite loop)
0.2 => 0.0011 0011 0011...(infinite loop)
The decimal part of a double-precision floating-point number can support up to 52 bits, so when you add them together, you get such a string of binary numbers that are truncated due to the decimal limit of a floating-point number, and then you convert it to decimal, you get 0.0000000000000004.
How to solve it?

First multiply the number by the power of 10 and remove the decimal places to get integers that can be converted to binary, then restore.

/** 
 ** A division function used to obtain an exact division result
 ** Note: The division result of javascript will be erroneous, which is more obvious when two floating point numbers are divided.This function returns a more precise division result.
 ** Call: accDiv(arg1,arg2)
 ** Return value: exact result of arg1 divided by 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) * Math.pow(10, t2 - t1);
    }
}

/**
 ** Addition function, used to obtain exact addition results
 ** Note: The result of javascript addition can be erroneous, which is more obvious when two floating point numbers are added together.This function returns a more precise addition result.
 ** Call: accAdd(arg1,arg2)
 ** Return value: exact result of arg1 plus 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;
}

/**
 ** Multiplication function, used to obtain exact multiplier results
 ** Note: Multiplication results of javascript will have errors, which will be more obvious when multiplying two floating-point numbers.This function returns a more precise multiplication result.
 ** Call: accMul(arg1,arg2)
 ** Return value: exact result of arg1 multiplied by 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);
}

Posted by rhecker on Mon, 16 Mar 2020 09:17:44 -0700