Всем привет! Сегодня разберёмся раз и навсегда, почему в JavaScript:
0.1 + 0.2 === 0.30000000000000004 // true
Кажется, что это баг в JS, но на самом деле — нет. JavaScript использует формат IEEE 754 double precision — это 64-битное представление чисел с плавающей точкой.
---
💡 Почему возникает ошибка?
Некоторые десятичные дроби, например
0.1 и 0.2, невозможно точно представить в двоичной системе. Они превращаются в бесконечные двоичные дроби.---
📐 Как `0.1` представляется в двоичной системе?
Чтобы перевести дробную часть числа в двоичную систему, мы умножаем её на 2 и фиксируем целую часть результата. Вот шаги:
0.1 * 2 = 0.2 → 0
0.2 * 2 = 0.4 → 0
0.4 * 2 = 0.8 → 0
0.8 * 2 = 1.6 → 1
0.6 * 2 = 1.2 → 1
0.2 * 2 = 0.4 → 0
0.4 * 2 = 0.8 → 0
0.8 * 2 = 1.6 → 1
0.6 * 2 = 1.2 → 1
... и так далее
🔁 В итоге мы получаем бесконечную периодическую двоичную дробь:
0.1₁₀ = 0.00011001100110011001100...₂
---
📦 Далее сдвигаем на 4 позиции. Почему?
Чтобы сохранить число в формате IEEE 754, его нужно записать в нормализованной форме:
1.значащие_биты × 2^экспонента
Мы сдвигаем запятую так, чтобы первая единица оказалась перед точкой:
0.0001 10011001100110011...
↓
1.10011001100110011... × 2⁻⁴
То есть сдвигаем на 4 позиции влево, и поэтому экспонента = -4. Это и есть часть формата IEEE 754.
---
🧮 Что делает JavaScript?
Он берёт ближайшее возможное двоичное значение, которое можно представить в 64 битах:
1.1001100110011001100110011001100110011001100110011010 × 2⁻⁴
Это — ровно 52 бита точности, и последняя цифра округлена вверх.
Теперь, если пересчитать это значение обратно в десятичную форму, получится:
0.1000000000000000055511151231257827021181583404541015625
То есть
0.1 в JS — это не ровно 0.1, а немного больше. Проверка:console.log(0.1.toPrecision(60))
// → '0.1000000000000000055511151231257827021181583404541015625'
---
📌 То же самое происходит с `0.2` — оно представляется как:
0.200000000000000011102230246251565404236316680908203125
Поэтому при сложении
0.1 + 0.2 мы получаем:≈ 0.3000000000000000444...
А
0.3 в памяти — это другое приближённое значение, поэтому:0.1 + 0.2 === 0.3 // false
---
Собственно говоря вот и вся магия 💫
📚 Кстати, про достоверные источники...
В универе на магистратуре в Англии нас всегда учили что все источники информации должны быть проверенными и надежными! Вот например Wikipedia вообще НЕ надежный источник информации 😂
И нам приходилось искать все эти проверенные статьи и мы гуглили не просто в Гугле а на https://scholar.google.com
Можете попробовать поискать информацию на https://scholar.google.com и вам выйдут только академические статьи.