Глава 5 · Давайте поиграем с числами!

Отладка вычислений

Неверное число без единой ошибки — самый коварный тип бага. Разберём три причины и надёжный способ их искать.

Формула, которая выдаёт неверное число, — гораздо коварнее, чем ошибка, которая роняет программу: Python не подскажет, что что-то не так. Разберём, как искать такие проблемы осознанно, а не методом «поменял и посмотрел».

Вычисление даёт нетот результат, чтоожидалосьСинтаксическаяошибкапрограмма вообще незапускается — Pythonуказывает на строку до…Ошибка в формулепрограмма работает, носчитает не то, чтозадумано — приоритет,…Особенностьпредставления чиселпрограмма работает и вродебы права, но сравнение илиокругление ведёт себя…
Три разных типа проблем — и три разных способа их искать

1. Синтаксическая ошибка

Самый простой случай — программа не запускается вовсе, и Python указывает на конкретную строку и символ ещё до начала выполнения:

sintaksicheskaya.py
# itog = (a + b * c
# SyntaxError: '(' was never closed — не хватает закрывающей скобки
Считайте скобки парами
Самый надёжный способ найти незакрытую скобку — считать открывающие и закрывающие скобки в подозрительной строке отдельно; их должно быть поровну.

2. Ошибка в формуле

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

ПричинаПримерГде мы это уже видели
забытые скобки4 + 7 + 9 / 3 вместо (4 + 7 + 9) / 3раздел «Скобки и формулы»
не та переменнаяprint(shirina + shirina) вместо print(perimetr)раздел «Скобки и формулы»
перепутанный приоритет-2 ** 2 — не то же самое, что (-2) ** 2раздел «Унарные операторы»

Приём: трассировка формулы через именованные шаги

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

trassirovka.py
# было — одна строка, непонятно, что пошло не так:
itog = (cena - skidka) * kolichestvo + dostavka / kolichestvo

# стало — видно каждый промежуточный результат:
cena_so_skidkoj = cena - skidka
print("Цена со скидкой:", cena_so_skidkoj)

summa_za_tovar = cena_so_skidkoj * kolichestvo
print("Сумма за товар:", summa_za_tovar)

dostavka_na_edinicu = dostavka / kolichestvo
print("Доставка на единицу:", dostavka_na_edinicu)

itog = summa_za_tovar + dostavka_na_edinicu
print("Итог:", itog)
итог = (100 − 10) × 3 + 15 / 3
цена со скидкой = 90
сумма за товар = 270
доставка на единицу = 5.0
итог = 275.0
Трассировка превращает одну загадочную строку в последовательность понятных, проверяемых шагов
Это временный код, а не постоянный
Разбиение на именованные шаги — приём именно для отладки. Когда формула заработает верно, промежуточные print() обычно убирают, но иногда осмысленные имена промежуточных переменных стоит оставить — они делают код понятнее, даже если он больше не в отладке.

3. Особенность представления чисел

Третья категория — код синтаксически верен, формула тоже верна, но результат всё равно удивляет. Обычно причина в том, что мы уже подробно разбирали в главе 4:

float_lovushka.py
print(0.1 + 0.2 == 0.3)          # False! — не баг, а особенность float
print(round(0.1 + 0.2, 10) == 0.3)  # True — сравнение с допуском работает верно
Подробности — в главе 4
Почему так происходит и как сравнивать float правильно — подробно разобрано в разделе «Сравниваем float правильно» главы 4. Здесь достаточно узнавать симптом: сравнение == между float ведёт себя неожиданно — значит, дело в представлении чисел, а не в ошибке формулы.

Предскажите, прежде чем запускать

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

★ Базовая практика
Предскажите результат

Не запуская код, определите результат: итог = 2 + 3 * 4 ** 2 // 5. Затем проверьте себя.

★★ Самостоятельная задача
Найдите ошибку в формуле

В коде srednyaya_ocenka = ocenka1 + ocenka2 + ocenka3 / 3 есть ошибка приоритета. Найдите и исправьте её.

★★★ Задача повышенной сложности
Трассируйте формулу

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

Практика: отладка вычислений
Интерактивный ноутбук прямо в браузере — Python 3.14 через Pyodide, без установки
Открыть практику →