Нашёл ответ:
Всё дело в том, что в стандарте IEEE 754 на число выделяется ровно 8 байт(=64 бита), не больше и не меньше.
Число 0.1 (одна десятая) записывается просто в десятичном формате. Но в двоичной системе счисления это бесконечная дробь, так как единица на десять в двоичной системе так просто не делится. Также бесконечной дробью является 0.2 (=2/10).
Двоичное значение бесконечных дробей хранится только до определенного знака, поэтому возникает неточность. Её даже можно увидеть:
alert( 0.1.toFixed(20) ); // 0.10000000000000000555
Когда мы складываем 0.1 и 0.2, то две неточности складываются, получаем незначительную, но всё же ошибку в вычислениях.
Есть два способа сложить 0.1 и 0.2:
- Сделать их целыми, сложить, а потом поделить:
alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3
- Сложить, а затем округлить до разумного знака после запятой. Округления до 10-го знака обычно бывает достаточно, чтобы отсечь ошибку вычислений:
var result = 0.1 + 0.2;
alert( +result.toFixed(10) ); // 0.3