This is the 28th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021
This question has been a platitude, it is also a frequent interview question, to understand the principle of it is not complicated, please follow me to explore the root of this problem
How do you store numbers in javascript
As we know, for a computer, it does not recognize numbers like 0.1 and 0.2, but only 0 and 1 binary strings. Therefore, to perform an operation on a number, it must first convert the number into a binary string and save it in the computer
Different languages use different storage methods to store numbers. In JS, both integers and decimals are Number types, and they are stored in the double precision floating point format under IEEE 754 standard, that is, 64 bits are used to store numbers. The 64 bits are divided into three parts, listed as follows:
- 1. Sign bit (S, symbol) used to indicate a sign, 0 being positive and 1 being negative (1 bit)
- 1. Exponent (E, exponent) : used to express a number to the power (11 bits).
- Mantissa (M, mantissa) : used to indicate precision (52 bits)
Note that for mantissa, the default first digit is 1 and can be omitted, so the actual mantissa is 53 bits
The first loss of accuracy
With that in mind, let’s first convert 0.1 and 0.2 to base 2
- 0.1: 00011001100110011001(1001)…
- 0.2: 00110011001100110011(0011)…
As you can see, 0.1 and 0.2, when converted to base 2, are an infinite loop of numbers
The computer certainly cannot store an infinite cycle of numbers, at this time will carry out precision interception, as we know from the above, js mantails up to 52 bits, so it will be interception according to the principle of entering 1 round 0, only retain 52 effective bits, note that this is the first time precision loss
Take 0.1 as an example to illustrate the specific conversion process. First, paste a formula
The precision bits are 53 bits in total, so the first fixed 1 takes up no space because of scientific notation. That’s the 1 in M plus 1. And 1023 in the formula is half of 2 to the 11th, so e less than 1023 is used for decimals, e greater than 1023 is used for integers
First 0.1 converts to binary 00011001100110011001(1001)… , expressed by scientific and technical method as 1.100110011… X 2^(-4), S is 0(1 bit), E is 1023-4 = 1019, corresponding to the binary bit 01111111011(11 bits). M to 1001100110011001100110011001100110011001100110011010 (52 bits)
A second loss of accuracy
After 0.1 and 0.2 get their respective approximations, the logarithmic order operation is required due to the different number of exponential digits. I didn’t go into the details of the calculation, but it is important to know that there is a rounding operation in this process, which again causes a loss of accuracy, and the final result is 0.1 + 0.2 = 0.30000000000000004
gossip
Through the above, we know that the results are not necessarily reliable when the four operations are carried out in JS. This section lists the special numbers provided in JS, which can help us avoid unreliable numerical calculations in daily development to some extent
- Number.EPSILON: The minimum interval between two representable numbers, which we pass to the question of whether 0.1+0.2 equals 0.3
0.1 + 0.2 0.3 < Number. The EPSILON
To solve the - Number.MAX_SAFE_INTEGER: the largest safe integer in JavaScript, 2^ 53-1
- Number.min_safe_integer: the smallest safe integer in JavaScript -(2^ 53-1)
- Number.MAX_VALUE: indicates the maximum positive Number that can be represented. The smallest negative number is -max_value
- Number.min_value: The smallest positive Number that can be represented is the closest positive Number to 0 (it does not actually become 0). The largest negative number is -min_value
conclusion
In fact, 0.1 + 0.2! == 0.3 problem is not only in JS, as long as any IEEE 754 specification language will have this problem, so we can not let JS to back the problem, and we have to do is through the phenomenon to see the essence, so as not to be confused by the appearance, so as to become an excellent engineer ~