On the front end, memory management is one of the most overlooked areas, because most of it is dealing with the UI. If you do not understand memory, you can not see the nature of many problems, it is difficult to write more qualified code, this time with you into the world of memory.

JS magic Number

Case 1: Calculation and transfer of amount

18.9 * 100
=1889.9999999999998
Copy the code

Case 2: A mathematical law violated

0.1 + 0.2= = =0.3
// false

(function (a, b, c) {
    return a + b + c === a + ( b + c )
})(0.1.0.2.0.3)
// false
Copy the code

Case 3: Infinite loop addition

(function (num) {
    while(true) {
        if (++num % 13= = =0) {
            return num
        }
    }
})(2* *53)
Copy the code

Case 4: json.parse

JSON.parse('{"a":180143985094813214124}')
//{a: 180143985094813220000}
Copy the code

Through the above four cases, we can see that the calculation of numbers in the computer often brings some “surprises” to people. To prevent these unexpected results, we should first understand how the Number is stored in Javascript.

Store the number

Computers store data in binary, so numbers need to be converted to different combinations of the corresponding binary: 000 or 111.

How to convert binary

Here’s an example of how to convert a number to binary:

The decimal fraction 106.6953125106.6953125106.6953125 into binary

When meeting decimal conversion, need to deal with the integer and decimal parts respectively, the integer 106106106 divided by 222 until the quotient is 000, take the remainder result of each division 222

106 / 2 = 53.0
53  / 2 = 26.1
26  / 2 = 13.0
13  / 2 = 6.1
6   / 2 = 3.0
3   / 2 = 1.1
1   / 2 = 0.1The result is that the remainder is arranged from right to left1101010
Copy the code

Decimal 0.69531250.69531250.6953125 multiplied by 222 until there is no decimal places, and gauge the results by the integer bit at a time,

0.6953125 x 2 = 1.390625.1
0.390625  x 2 = 0.78125.0
0.78125   x 2 = 1.5625.1
0.5625    x 2 = 1.125.1
0.125     x 2 = 0.25.0
0.25      x 2 = 0.5.0
0.5       x 2 = 1.1The resulting integer bits are arranged from left to right1011001
Copy the code

Will be calculated sequence of 000 111 have conversion of binary 1101010.10110011101010.10110011101010.1011001 together, Represented by scientific notation as 1.1010101011001∗261.1010101011001*2^ 61.101010101011001 ∗26, the binary has been calculated, which then needs to be stored in the computer without distinguishing integers from decimals in Javascript, Digits are stored in accordance with the requirements of double precision floating point numbers, mainly including the following rules:

  • Use 8bytes(64bits)8bytes(64bits)8bytes(64bits) to store a double precision floating point number
  • Store decimal data expressed in scientific notation
  • The first digit represents the symbol, and the last digit represents the index. The index is calculated according to the complement, that is, the index digit is directly added to 102310231023
  • The remaining 525252 digits represent the mantissa after the decimal point, and the portion exceeding 525252 digits is 000 and 111 decimal places

Since the 11 bits of the exponent do not include the sign bit, the offset value of the exponent is introduced to achieve the effect of positive and negative exponents.

It is shown as follows:

We will convert binary number according to the rules in memory, first 106.6953125106.6953125106.6953125 is positive, so the sign bit should be 000, 000 plus, minus 111 said

Binary 1.1010101011001∗ 261.101010101011001 *2^ 61.101010101011001 ∗26 is 666 (offset 1023 needs to be added here), Converted to binary for 100000001011000000010110000000101, the index requirements placed binary complement, and complement calculation rule is:

  • The complement of a positive number is itself
  • The complement of a negative number is based on its original code, the sign bits remain unchanged, the other bits are reversed, and finally +1.
[+1] = [00000001Original = []00000001] the [...1] = [10000001Original = []11111110] theCopy the code

So the index bit of the picture should be filled in

The mantissa part can be directly filled in the binary after the decimal conversion

That’s how the numbers end up in the computer

Why 0.1 + 0.2! = = 0.3?

After understanding the principle of digital storage, let’s analyze why 0.1+0.2! = = 0.30.1 + 0.2! = = 0.30.1 + 0.2! = = 0.3

First, 0.10.10.1 0.20.20.2 0.30.30.3 was converted to binary respectively

0.1 x 2 = 0.2.0
0.2 x 2 = 0.4.0
0.4 x 2 = 0.8.0
0.8 x 2 = 1.6.1
0.6 x 2 = 1.2.1
0.2 x 2 = 0.4.0
0.4 x 2 = 0.8.0
0.8 x 2 = 1.6.1
0.6 x 2 = 1.2.1The resulting integer bits are arranged from left to right000110011.Copy the code


0.1 0.00011 ( 0011 ) up 0.1 0.00011 (0011) _ \ rightarrow \ infty

0.2 x 2 = 0.4.0
0.4 x 2 = 0.8.0
0.8 x 2 = 1.6.1
0.6 x 2 = 1.2.1
0.2 x 2 = 0.4.0
0.4 x 2 = 0.8.0
0.8 x 2 = 1.6.1
0.6 x 2 = 1.2.1
0.2 x 2 = 0.4.0The resulting integer bits are arranged from left to right001100110.Copy the code


0.2 0.00110 ( 0110 ) up 0.2 0.00110 (0110) _ \ rightarrow \ infty

0.3 x 2 = 0.6.0
0.6 x 2 = 1.2.1
0.2 x 2 = 0.4.0
0.4 x 2 = 0.8.0
0.8 x 2 = 1.6.1
0.6 x 2 = 1.2.1
0.2 x 2 = 0.4.0
0.4 x 2 = 0.8.0
0.8 x 2 = 1.6.1The resulting integer bits are arranged from left to right010011001.Copy the code


0.3 0.01001 ( 1001 ) up 0.3 0.01001 (1001) _ \ rightarrow \ infty

Uniformly expressed in scientific notation as


0.1 0.00011 ( 0011 ) up 1. ( 1001 ) up 2 4 0.1 \ RightarRow 0.00011(0011)_\ Infty \ rightarRow 1.(1001)_\ Infty *2^{-1}


0.2 0.00110 ( 0110 ) up 1. ( 1001 ) up 2 3 \infty*2^{-2} \infty*2^{-2} \infty*2^{-2}


0.3 0.01001 ( 1001 ) up 1. ( 0011 ) up 2 2 0.3 \ RightarRow 0.01001(1001)_\infty \ rightarRow 1.(0011)_\ Infty *2^{-2}

In the computer, a double precision floating-point number is stored, and the red at the end indicates the binary beyond the mantras, which is rounded to 1

After 64-bit double precision storage, the binary is represented as follows


0.1 0 01111111011 ( 1001 ) 12 1010 0.1 \ rightarrow 0-01111111011-1010 (1001) _ {12}


0.2 0 01111111100 ( 1001 ) 12 1010 0.2 \ rightarrow 0-01111111100-1010 (1001) _ {12}


0.3 0 01111111101 ( 0011 ) 12 0011 0.3 \ rightarrow 0-01111111101-0011 (0011) _ {12}

At this point, it can be seen that 0.1+0.20.1 +0.20.1 +0.2 is not equal to 0.30.30.3

This is the number in the computer calculation often bring some “surprise”!

conclusion

If this article is helpful, please like it at 😯

If there are mistakes in the article, welcome to correct; If you have additional information, please leave a message.