Why 0.1+0.2 !== 0.3 in JavaScript?
Not just that, but why is 0.1*0.1 = 0.010000000000000002 and not 0.01? Why is 1.1-1.0 = 0.10000000000000009 and not 0.1?

Full Stack Developer
Is JS incapable of solving these simple math problems? 🧐
Understanding the problem
All the number systems like decimal, binary, hexadecimal etc. have some limitations or edge cases. E.g.: The number of 3's after the decimal point in 1/3 is more than the number of atoms in the observable universe. When you divide 1 by 3, you'll always end up with 1 as the remainder. The no. of 3's in the quotient just keeps increasing, and we say that it is impossible to represent 1/3 exactly in decimal number system. We always use the approximate value of 1/3 in decimal number system.
Similarly, it is impossible to exactly represent 1/10 in binary system. 1/10 in binary number system is 0.0001100110011001100110011... (with the 0011 repeating infinitely).
What happens in JS?
JavaScript uses IEEE 754 standard i.e., "Double-precision floating-point" also known as binary64 for its mathematical calculations, where it considers all decimal numbers as 64-bit binary floating numbers. In this, 1 bit is used for Sign bit, 11 bits for exponent and 53 bits (52 explicitly stored) for Significand precision.
When the code is interpreted, all the numbers are converted to closest floating point numbers with rounding off errors in some cases. When any mathematical operations are done on these interpreted numbers, the result may not be as expected.
As per our initial question, 0.1 can be closely represented by the following binary64 number:
0.00011001100110011001100110011001100110011001100110011010
and 0.2 can be closely represented in binary64 format by:
0.00110011001100110011001100110011001100110011001100110100
The real number sum of these two numbers is:
0.01001100110011001100110011001100110011001100110011001110
This number has 54 significant digits (56 digits are shown above, but leading 0 is for alignment and trailing 0 has no significance to the value). But binary64 can only store 53 digits for the significand value, so this number cannot be represented in binary64 format.
This number is exactly between two binary64 representable numbers:
0.01001100110011001100110011001100110011001100110011001100and,
0.01001100110011001100110011001100110011001100110011010000
In case of a tie, the number with an even digit in the lowest position is chosen.
Therefore, our final answer in binary64 format is:
0.01001100110011001100110011001100110011001100110011010000and in the decimal number system, it is:
0.3000000000000000444089209850062616169452667236328125
So, 0.1 + 0.2 = 0.3000000000000000444089209850062616169452667236328125. Let's call this value 'A'.
But 0.3 is represented closely in binary64 format by:
0.010011001100110011001100110011001100110011001100110011which, in the decimal number system, is:
0.299999999999999988897769753748434595763683319091796875Let's call this value 'B'.
Since, A !== B, 0.1+0.2 !== 0.3 returns true. Also, if you do 0.1 + 0.2, you will get 0.30000000000000004, which is the rounded-off value for 0.3000000000000000444089209850062616169452667236328125.
Conclusion
It is because of binary64 format, which is used by JavaScript internally, just like many other programming languages, that we get to see this behaviour working with numbers.
We should be careful when our program has complex calculations involving very large or very small, or a combination of both numbers. The program should take into account rounding off, truncation and precision of calculations required.
References
Very detailed article (I didn't go through it completely)
