preface

Most languages have problems with accuracy when dealing with floating point numbers, but it seems to be particularly severe in JS, such as console.log(1.1-0.5); The result is 0.6000000000000001. Addition, subtraction, multiplication, division, etc.

Is this a JS error?

Today, big ice cube will talk about this problem.

Binary floating point operation

In fact, your computer is doing correct binary floating-point arithmetic, but the problem is that you’re putting in decimal numbers, and the computer is working in binary, and the two don’t always translate that well, and sometimes you get the right result, but sometimes you’re not so lucky.

alert(0.7+0.1)    / / output 0.7999999999999999
alert(0.6+0.2)    / / output 0.8
Copy the code

You take two decimal numbers, you convert them to binary and then you convert them back, and you lose something in the process.

But the general loss is often more in the multiplication and division operation, and JS in the simple addition and subtraction will also appear this kind of problem, although the error is very small, but it is not supposed to appear.

There is a simple logic, such as 0.7+0.1, first multiply 0.1 and 0.7 by 10, then divide by 10.

Following this logic, we can encapsulate addition, subtraction, multiplication and division as follows:

        (function () {
            var calc = {

                Arg1 = arg1; arg1 = arg1; arg1 = arg1; arg1 = arg1; arg1 = arg1 Arg2 second addend; Calc.Add(arg1,arg2,d) Return value: the result of adding two numbers. The return type is string */
                Add: function (arg1, arg2, d) {
                    // Pass arg1 and arg2 into strings and cut them to get the number of decimal points
                    let arg1Arr = arg1.toString().split("."), arg2Arr = arg2.toString().split("."), d1 = arg1Arr.length == 2 ? arg1Arr[1] : "", d2 = arg2Arr.length == 2 ? arg2Arr[1] : ""
                    d = typeof d === "number" ? parseInt(d) : Math.max(d1.length, d2.length) // The number of decimal places reserved is equal to the number of decimal places passed in d or two numbers
                    let m = Math.pow(10, d) // Raise 10 to the maxLen
                    return Number(((arg1 * m + arg2 * m) / m).toFixed(d)) // Check whether the passed d type is number. If yes, cut the d bit after the decimal point.
                },

                Arg1: the first addend; arg1: the first addend; arg1: the subtraction function. Arg2 second addend; Calc.Sub(arg1,arg2,d) returns the result of subtracting two numbers */
                Sub: function (arg1, arg2, d) {
                    return Calc.Add(arg1, -Number(arg2), d)
                },

                /* Function: multiplication function, used to get exact multiplication results description: function returns more accurate multiplication results. Arguments: arg1: the first multiplier; Arg2 second multiplier; Mul(arg1,arg2,d) returns the result of multiplying two numbers */
                Mul: function (arg1, arg2, d) {
                    d = typeof d === "number" ? parseInt(d) : (arg1.toString().split(".") [1]? arg1.toString().split(".") [1].length : 0) + (arg2.toString().split(".") [1]? arg2.toString().split(".") [1].length : 0)
                    return Number(arg1.toString().replace("."."")) * Number(arg2.toString().replace("."."")) / Math.pow(10, d) 
                },

                /* Function: division function, used to get accurate division results description: The function returns more accurate division results. Arguments: arg1: divisor; Arg2 dividend; Div(arg1,arg2,d) returns: arg1 divided by arg2 */
                Div: function (arg1, arg2, d) {
                    d = typeof d === "number" ? parseInt(d) : (arg2.toString().split(".") [1]? arg2.toString().split(".") [1].length : 0) - (arg1.toString().split(".") [1]? arg1.toString().split(".") [1].length : 0)
                    return Number(arg1.toString().replace("."."")) / Number(arg2.toString().replace("."."")) * Math.pow(10, d)
                }
            };
            window.Calc = calc; } ());Copy the code

This method returns a string because:

The toFixed(num) method returns a string representation of a NumberObject. It does not use an exponential counting method, but has a fixed num number behind the decimal point. If necessary, the number is rounded or supplemented with 0 so that it reaches the specified length. If num is greater than le+21, numberObject.toString () is called, which returns the string in exponential notation.

Reference article:

www.iteye.com/blog/talent… Blog.csdn.net/baidu_29701… Blog.csdn.net/yexuan14/ar…

Afterword.

Hello, I am the South Pole ice cube, a technology and appearance level proportional to the front-end engineer, advocating to solve front-end problems, I hope my blog has helped you. Pay attention to me and walk together on the front road. Hey ~ 😛