JS floating point calculation error explanation and solution

1 Overview

Floating-point numbers refer to numerical values ​​with decimals. Floating-point arithmetic is the four arithmetic of decimals, and is often used to measure the speed of computer operations. Most computers use binary (b=2) representation. Bit (bit) is a measure of the storage space required for floating-point numbers, usually 32 bits or 64 bits, which are called single precision and double precision, respectively.

2 Error phenomenon

console.log(0.1+0.2);    // 输出 0.30000000000000004
console.log(0.15+0.15);  // 输出 0.3
 
console.log(0.7+0.1);    // 输出 0.7999999999999999
console.log(0.6+0.2);    // 输出 0.8
 
console.log(0.3*3);      // 输出 0.8999999999999999
console.log(3*3/10);     // 输出 0.9

It can be seen from the above phenomenon that not all floating-point arithmetic will have problems, only some of them.

0.7+0.1 Output has deviation

0.6+0.2 The output is correct

What is the specific reason? Continue to look down.

3 Causes of error

Not only JS, most languages ​​will encounter precision problems when dealing with floating-point numbers. To be precise, this phenomenon exists in all systems that support binary floating-point operations (most of them are implemented by IEEE 754).
The reason is that under the limited storage space, most decimal decimals cannot be accurately represented by binary floating point numbers. For example, the simple decimal fraction of 0.1 cannot be represented by a binary floating point number. The so-called "computer floating point number" is actually the binary "scientific notation". In decimal, the form of scientific notation is:
Insert picture description here
Correspondingly, the scientific notation of binary is:
Insert picture description here
and in limited storage space, the decimal fraction 0.1 can’t be expressed in this form anyway, so when the computer stores it , Resulting in a loss of accuracy, so the phenomenon described in the problem occurs.
For more details, please click on the link to view https://www.zhihu.com/question/20679634

4 Solution

How to solve it? Look at this example:

console.log(0.3*3);      // 输出 0.8999999999999999
console.log(3*3/10);     // 输出 0.9

There is a problem with floating-point calculations. Integer calculations are okay. Then convert floating-point to integer arithmetic, and then switch back to floating-point to ensure that there is no deviation

Note: js is not recommended to do too many floating point operations.

The following methods can help you correct the deviation of floating-point operations:

// 浮点数求和
function add(a, b) {
    
    
    var c, d, e;
    try {
    
    
        c = a.toString().split(".")[1].length;
    } catch (f) {
    
    
        c = 0;
    }
    try {
    
    
        d = b.toString().split(".")[1].length;
    } catch (f) {
    
    
        d = 0;
    }
    return e = Math.pow(10, Math.max(c, d)), (mul(a, e) + mul(b, e)) / e;
}
 
// 浮点数相减
function sub(a, b) {
    
    
    var c, d, e;
    try {
    
    
        c = a.toString().split(".")[1].length;
    } catch (f) {
    
    
        c = 0;
    }
    try {
    
    
        d = b.toString().split(".")[1].length;
    } catch (f) {
    
    
        d = 0;
    }
    return e = Math.pow(10, Math.max(c, d)), (mul(a, e) - mul(b, e)) / e;
}
 
// 浮点数相乘
function mul(a, b) {
    
    
    var c = 0,
        d = a.toString(),
        e = b.toString();
    try {
    
    
        c += d.split(".")[1].length;
    } catch (f) {
    
    }
    try {
    
    
        c += e.split(".")[1].length;
    } catch (f) {
    
    }
    return Number(d.replace(".", "")) * Number(e.replace(".", "")) / Math.pow(10, c);
}
 
// 浮点数相除
function div(a, b) {
    
    
    var c, d, e = 0,
        f = 0;
    try {
    
    
        e = a.toString().split(".")[1].length;
    } catch (g) {
    
    }
    try {
    
    
        f = b.toString().split(".")[1].length;
    } catch (g) {
    
    }
    return c = Number(a.toString().replace(".", "")), d = Number(b.toString().replace(".", "")), mul(c / d, Math.pow(10, f - e));
}

verification

console.log(0.1+0.2);        // 输出 0.30000000000000004
console.log(add(0.1, 0.2));  // 输出 0.3
 
console.log(0.7+0.1);        // 输出 0.7999999999999999
console.log(add(0.7, 0.1));  // 输出 0.8
 
console.log(0.3*3);          // 输出 0.8999999999999999
console.log(mul(0.3, 3));    // 输出 0.9

The blog post comes from Zhihu and other blogs, thanks!

Guess you like

Origin blog.csdn.net/qq_41800366/article/details/102754335