Архив рубрики ~Лента новостей~

Почему 0.1 + 0.2 не равно 0.3: как ПК хранит дробные числа?

Почему 0.1 + 0.2 не равно 0.3: как ПК хранит дробные числа?
Почему 0.1 + 0.2 не равно 0.3: как ПК хранит дробные числа?

Почему 0.1 + 0.2 не равно 0.3: как ПК хранит дробные числа?

Компьютер не ошибается, складывая 0.1 и 0.2. Проблема в том, что многие десятичные дроби невозможно точно записать в двоичной системе. Разбираемся без сложной математики.

Почему 0.1 + 0.2 не равно 0.3?

Откройте консоль браузера и выполните простое сложение:

0.1 + 0.2 // 0.30000000000000004

Выглядит так, будто JavaScript не справился с арифметикой начальной школы. Но язык здесь ни при чём. Похожий результат можно получить в Python, Java, C++ и многих других языках.

Компьютер посчитал всё правильно. Просто значения 0.1 и 0.2 изначально хранились с крошечной погрешностью.

Дело в двоичной системе

Мы привыкли записывать числа в десятичной системе. В ней дробь 0.1 выглядит идеально: одна цифра после запятой, никакой неоднозначности.

Компьютер хранит данные с помощью битов, поэтому дробные числа обычно переводятся в двоичную систему. И здесь начинается проблема: десятичное значение 0.1 невозможно представить конечным количеством двоичных цифр.

Получается бесконечная последовательность, похожая на привычную дробь 1 / 3 = 0.333333…. Мы не можем записать все тройки и вынуждены остановиться на каком-то месте. Компьютер делает то же самое с 0.1, только в двоичной системе.

Что на самом деле хранится в памяти

Большинство языков использует стандарт IEEE 754. Обычное 64-битное число с плавающей точкой состоит из знака, порядка и мантиссы. Мантисса хранит значимые цифры, а порядок определяет положение двоичной точки.

Места ограничены, поэтому бесконечную дробь приходится округлять до ближайшего доступного значения. Вместо точного 0.1 в памяти оказывается число примерно такого вида:

0.10000000000000000555…

У 0.2 тоже появляется небольшое отклонение. После сложения погрешности складываются, и ближайшим представимым результатом становится 0.30000000000000004.

При обычном выводе лишние цифры часто скрываются. Но если результат нельзя красиво сократить без потери информации, язык показывает его полностью.

Погрешность мала, но сравнение ломается

Разница настолько мала, что для большинства бытовых расчётов она ничего не меняет. Однако прямое сравнение может неожиданно вернуть false:

0.1 + 0.2 === 0.3 // false

Поэтому дробные результаты обычно сравнивают с допустимой погрешностью:

const result = 0.1 + 0.2; const expected = 0.3; const epsilon = 1e-10; Math.abs(result — expected) < epsilon; // true

Здесь мы спрашиваем не «совпадают ли числа до последнего бита», а «достаточно ли они близки для нашей задачи».

Правда, брать одно и то же значение epsilon повсюду тоже не стоит. Допустимая ошибка зависит от масштаба чисел и смысла расчёта. Требования к координатам элемента интерфейса и к научной модели будут разными.

С деньгами лучше не рисковать

Особенно неприятно встретить такую погрешность в расчёте цен, налогов и скидок. Округление результата только перед выводом не всегда спасает: ошибка может накопиться раньше и повлиять на условие, итоговую сумму или распределение платежей.

Для денег часто используют целые минимальные единицы. Вместо 19.99 доллара программа хранит 1999 центов. Целые числа представляются точно, пока не выходят за поддерживаемый диапазон.

const priceCents = 1999; const quantity = 3; const totalCents = priceCents * quantity; console.log(totalCents / 100); // 59.97

Другой вариант — специальные десятичные типы и библиотеки вроде Decimal. Они нужны там, где точность важнее скорости и удобства обычных чисел с плавающей точкой.

Почему тогда не хранить все дроби точно?

Можно, но за точность приходится платить памятью и скоростью. Числа с плавающей точкой удобны тем, что компактно описывают огромный диапазон значений и быстро обрабатываются процессором.

Для графики, игр, физики, машинного обучения и большинства инженерных вычислений небольшая погрешность вполне приемлема. Там важнее скорость миллионов операций, а не абсолютная точность каждой дроби.

Ошибка начинается не в формате числа, а в неверных ожиданиях разработчика. Если задача допускает приближение, обычный float подходит отлично. Если требуется точное количество денег, голосов или товаров, лучше выбрать другое представление.

Компьютер не ошибся

Результат 0.30000000000000004 выглядит странно только потому, что мы видим двоичную погрешность в десятичной записи. Сам компьютер последовательно работает с теми значениями, которые смог разместить в памяти.

Поэтому пытаться «исправить JavaScript» бессмысленно. Гораздо полезнее заранее решить, какая точность нужна программе, как сравнивать результаты и в каком формате хранить критичные данные.

И тогда загадка 0.1 + 0.2 перестаёт быть багом. Это обычный компромисс между точностью, диапазоном чисел и скоростью вычислений.

Источник

❌ Нет похожих статей с такими тегами

Оцените материал:

Поделиться
Понравилась статья? Расскажите другим
ВКонтакте
Читайте также
Архив рубрики ~Коротко из Telegram~ На хрен твоя жопа пойдёт, ебанашка Новости робототехники Искусственный интеллект в БПЛА: преимущества и риски Новости робототехники Новая система искусственного интеллекта поможет машинам более детально понимать трехмерное пространство. Новости робототехники Ростех показал кобота с «умным» зрением Новости робототехники ДНК-роботы могли бы доставлять лекарства и выслеживать вирусы внутри вашего тела. Новости робототехники Человекоподобные роботы, играющие в футбол, забили важный гол в области робототехники, продемонстрировав высокую координацию движений. Архив рубрики ~Коротко из Telegram~ Здравствуйте! Предлагаю участие в совместном конкурсе в Telegram, где вы… Новости робототехники Специалист по робототехнике утверждает, что безопасность человекоподобных роботов должна быть первостепенной задачей. Новости робототехники Приводимый в движение мышечными клетками, тончайший, как бумага, робот плывет по водному лабиринту. Архив рубрики ~Коротко из Telegram~ Поселил ИИ‑агента в чёлку макбука: он слушает мой день и… Архив рубрики ~Коротко из Telegram~ Немой парень впервые признался в любви СИЛОЙ МЫСЛИ — его………… Новости робототехники GM делает ставку на вычислительные технологии и искусственный интеллект, которые, по её мнению, помогут ей конкурировать с китайскими автопроизводителями. Архив рубрики ~Коротко из Telegram~ В легендарный Need for Speed: Underground 2 теперь можно поиграть… Архив рубрики ~Коротко из Telegram~ ИИ придумал пистолет, и его напечатали на 3D-принтере Однозарядный пистолет… Архив рубрики ~Коротко из Telegram~ На хрен твоя жопа пойдёт, ебанашка Новости робототехники Искусственный интеллект в БПЛА: преимущества и риски Новости робототехники Новая система искусственного интеллекта поможет машинам более детально понимать трехмерное пространство. Новости робототехники Ростех показал кобота с «умным» зрением Новости робототехники ДНК-роботы могли бы доставлять лекарства и выслеживать вирусы внутри вашего тела. Новости робототехники Человекоподобные роботы, играющие в футбол, забили важный гол в области робототехники, продемонстрировав высокую координацию движений. Архив рубрики ~Коротко из Telegram~ Здравствуйте! Предлагаю участие в совместном конкурсе в Telegram, где вы… Новости робототехники Специалист по робототехнике утверждает, что безопасность человекоподобных роботов должна быть первостепенной задачей. Новости робототехники Приводимый в движение мышечными клетками, тончайший, как бумага, робот плывет по водному лабиринту. Архив рубрики ~Коротко из Telegram~ Поселил ИИ‑агента в чёлку макбука: он слушает мой день и… Архив рубрики ~Коротко из Telegram~ Немой парень впервые признался в любви СИЛОЙ МЫСЛИ — его………… Новости робототехники GM делает ставку на вычислительные технологии и искусственный интеллект, которые, по её мнению, помогут ей конкурировать с китайскими автопроизводителями. Архив рубрики ~Коротко из Telegram~ В легендарный Need for Speed: Underground 2 теперь можно поиграть… Архив рубрики ~Коротко из Telegram~ ИИ придумал пистолет, и его напечатали на 3D-принтере Однозарядный пистолет…

Оставить комментарий