## Why is 0.1 + 0.2 not equal to 0.3?

tomee 2021-04-07 21:48:15
equal

# The problem background

It's a question that's likely to be asked in an interview , After online access to a variety of information 、 Articles, etc , There are descriptions of this problem . But the details and some key points need to be carefully studied and pondered to understand . In the process of figuring out this problem, we have experienced a lot of ideological struggles , So it's still necessary to record and share your insights .

# Theoretical basis

First , Be clear about all the calculations in the program , Going to the bottom of the computer is binary Computing , and , Binary computation has no concept of subtraction , The subtraction will be calculated by adding a negative number .

One more thing to note ,0.1+0.2 It's not equal to 0.3 It's not just about JavaScript in , Follow in other areas IEEE 754 This problem also exists in standard programming languages .JavaScript There is only one type for all numbers, including integers and decimals — Number. Its implementation follows  IEEE 754  standard , Use 64 Bit fixed length , That's standard double Double precision floating point （ There's more to it float 32 Bit single precision ）.

# Concrete realization

The whole calculation process goes through the following steps ：

1. Decimal to binary .
2. Binary to scientific notation .
3. Memory is used to analyze the data represented by scientific notation 、 Storage .
4. Operations on orders .
6. Rounding operation .
7. Binary to decimal .

## Decimal to binary

Back to the question itself , Let's start with how to put 0.1 Convert it to the underlying storage of the computer ,0.2 The idea of the transformation is clear . How to convert decimal to binary , Reference resources Novice tutorial that will do , No more details here .0.1 The conversion to binary is like this ： Go back and you'll find , This process is an infinite loop state . Never mind that , Write it down first ：

0.00011(0011)…

## Binary to scientific notation

Next, should we deal with infinite loops ？ Not at all , We know , In everyday decimal operations , We want to represent as much data as possible , Will use scientific notation . The same goes for the bottom layer of the computer , As we mentioned earlier ,JavaScript In order to double precision storage Number type , Therefore, if the data is converted to binary and stored directly , So the maximum number it can store is 263（ The first bit is the sign bit ）, In today's data age , This computable range is quite limited . therefore , Binary data should also be converted into scientific notation , Then the scientific notation is stored in parts ：

1.1(0011)… * 2-4（ Move the decimal point to the right 4 position , The base of binary is 2）

## Binary representation of scientific notation data

OK, The next question is , The computer 64 How do bits store scientific notation ？ This icon shows 64 Bit binary different parts of the stored data label . First , The highest bit is the sign bit , So it can't participate in the task of storing data , The subsequent 11 position （ Index part ） Binary number used to store the index in scientific notation , remainder 52 position （ Mantissa part ） It is used to store the decimal point of mantissa in scientific notation 52 position . The sign bits and mantissa of these three parts are very clear , Sign bit 0 It means a positive number ,1 A negative number ; The mantissa part of science is just the mantissa part 52 position ; The determination of the index part is a little more complicated .

Memory gives 11 Bit binary gives exponent , therefore ,11 If bit binary is converted to decimal , The range of data that can be stored is ：[0, 211], namely `[0, 2048]`. But there's a problem , The index can also be negative ！ How do negative numbers mean ？ Don't 11 The bit has to give up another bit to represent the sign bit ？ Not at all , In this part of the processing ,IEEE754 The standard index is 0 The cardinal number of is 1023（ With 1023 As the dividing line between positive and negative numbers ）, It's equivalent to being able to store `[-1023, 1024]` The number of this range . therefore , With 0.1 Take the index converted to scientific notation as an example , Index -4 Will be converted into `1023 - 4 = 1019`, And then convert it to binary ： 1019 It's converted to binary ：1111111011. therefore ,0.1 Before the final binary 12 Position as ：

001111111011

Next , The mantissa is reserved for 52 position , What about infinite loops ？ It's time to Rounding operation , follow 0 House 1 The principle of entry （ It is similar to the meaning of rounding in decimal system ）, This is also the key point of this issue , Rounding makes the data lose some precision .

You may wonder , A simple calculation can lead to the deviation of the calculation results , So is the result of a slightly more complex operation reliable ？ Of course it's reliable . firstly , It's rare to see an infinite loop in such a transformation , Even if there is , The double precision storage provided by the computer can also ensure that the data operation is within the allowable error range ; second , The bottom layer of the computer has a processing mechanism for precision error calculation , Calculation will not be allowed to go further and further on the road of deviation .

0.1 The final binary form is like this ：

0 01111111011 1001100110011001100110011001100110011001100110011010

0.2 The binary storage of is ：

0 01111111100 1001100110011001100110011001100110011001100110011010

## Operations on orders

The next step is to do the addition , Binary addition is not difficult , It's like the decimal system . But it's not easy , Before we will 0.1 and 0.2 When it comes to scientific notation , We found that 0.1 My index is -4,0.2 My index is -3. If you want to express the results of their operations in a scientific way , We have to unify the exponents and then extract the common factor for calculation . Here's a question Operations on orders , To minimize the loss of accuracy , We need to follow the small order to the large order （ That is, to convert a smaller index into a larger one ） Principles . In this case , We need to unify the index into -3. therefore ,0.1 After the operation of the order of the binary , That's true ：

0 01111111100 (0.)1100110011001100110011001100110011001100110011001101.

The mantissa needs to be shifted one bit to the right , Move the excess right to round . The integer part omitted by default 1 It's moved to the decimal part , So the integral part becomes 0.

Next, when you do the addition , To complete the integer part omitted before the mantissa , Because when there is carry , The integral part can change , This is also to facilitate the subsequent adjustment of the calculation results .

The result of adding mantissa is ：

10.0110011001100110011001100110011001100110011001100111 ## Rounding operation

There are two problems with this result ：

1. It doesn't conform to the rules of scientific notation .
2. The mantissa part exceeds the number of digits .

So adjust the results , First, change the result to “1.” At the beginning , The decimal point is shifted one place to the left , become ：

1.00110011001100110011001100110011001100110011001100111

meanwhile , Add the index to 1： become ：

01111111101

Last , Still based on 0 House 1 The principle of entry , Put the mantissa part beyond 52 The part outside the bit is rounded , The result is ：

1.0011001100110011001100110011001100110011001100110100

therefore , The complete result is ：

0 11111111101 (1.)0011001100110011001100110011001100110011001100110100

## Binary to decimal

Converting to decimal is ：

0.30000000000000004

thus , All the steps and detailed analysis of this problem have come to an end .

# summary

1. JavaScript Decimals are at the bottom of the computer with double precision （ namely 64 position ） How to store .
2. There are many precision losses in the whole process ： Operations on orders 、 Addition operation .
3. The loss of precision is essentially the result of rounding operations , When it comes to rounding operations, we have to follow 0 House 1 The principle of entry .

https://qdmana.com/2021/04/20210407213623157f.html