Почему round(2.675, 2) в Python выводит 2.67
@python_quizРазберем этот квиз
Коротко: код

печатает 2.67. Это выглядит неожиданно, если думать в десятеричной арифметике, но логично для двоичного представления чисел с плавающей точкой. Разберёмся, почему так происходит и как получить «ожидаемое» поведение.
Что происходит в коде
- Число 2.675 в памяти хранится не как точная десятеричная дробь 2.675, а как двоичная приближённая величина.
- При преобразовании десятеричной дроби в двоичную получается значение чуть меньше 2.675 (примерно 2.6749999999999998).
- Функция round смотрит на это фактическое значение и округляет «вниз» до 2.67.
Демонстрация (показываем внутреннее представление)

Одна из форм вывода ясно показывает, что float равен примерно 2.6749999999999998 — отсюда и поведение округления.
Решение, если нужно «идеальное» десятеричное округление
Для финансовых расчётов и там, где важна десятеричная точность, используйте модуль decimal:

Если хотите простое и надёжное десятеричное поведение — передавайте строковое представление в Decimal.
Анализ вариантов (коротко)
- "2.67" — именно такой результат даёт приведённый код в обычном CPython благодаря внутреннему представлению float.
- "2.68" — это ожидаемое десятеричное округление числа 2.675, но для float в памяти число хранится немного меньше, поэтому результат отличается.
- "Ошибка округления" — ошибки как исключения здесь нет; это преднамеренное следствие представления чисел с плавающей точкой.
- "Зависит от версии Python" — поведение обусловлено IEEE‑754 float и тем, как представляются двоичные приближения, а не версией языка; для практических целей результат одинаков в современных реализациях CPython.
Выводы и рекомендации
- Округления вида round(float, n) зависят не только от логики округления, но и от представления числа в памяти.
- Для точного десятеричного округления используйте decimal с передачей литерала в виде строки или храните значения в целых (копейки, центы) и округляйте целыми арифметическими операциями.
- Для диагностики всегда полезно посмотреть полное представление float через format(x, '.17f') или Decimal.from_float(x), чтобы убедиться, какое фактическое значение хранится в переменной.