round в Python: .5 → четное и проблема 2.675
@python_quizРазберем этот квиз
Код квиза:

Вывод:

Коротко о сути
Два разных явления объясняют этот результат:
- При значениях вида X.5 Python использует округление "к ближайшему чётному" (bankers rounding).
- Представление чисел с плавающей точкой не всегда соответствует десятичному литералу; 2.675 в памяти — немного меньше, поэтому при округлении до 2 знаков получается 2.67.
Округление .5 — почему 2.5 → 2, 3.5 → 4, -1.5 → -2
Правило: при точном значении с дробной частью .5 округление выполняется к ближайшему чётному целому.
- 2.5 находится между 2 и 3; ближайшее чётное — 2.
- 3.5 находится между 3 и 4; ближайшее чётное — 4.
- -1.5 находится между -2 и -1; ближайшее чётное — -2.
Наглядный пример:

Такое поведение помогает снижать систематическую ошибку при суммарном округлении (статистически более нейтральное).
Почему round(2.675, 2) даёт 2.67
Число 2.675 в десятичном виде не представимо точно в формате IEEE 754 double. В памяти оно хранится как значение чуть меньше 2.675 (примерно 2.6749999999999998). Это видно из представления:

Если требуется точное десятичное округление по правилам математической десятичной арифметики, используйте модуль decimal и строковые литералы:

Обратите внимание: Decimal('2.675') хранит именно десятичный 2.675 и при округлении по правилам "к ближайшему чётному" даст 2.68, в то время как Decimal(2.675) сначала получает уже искажённое двоичное представление.
Разбор вариантов ответов (коротко)
- "Выведет: 2 4 -2 2.67" — совпадает с реальным выводом программы.
- "Выведет: 2 4 -2 2.68" — неверно из‑за поведения представления float: 2.675 в памяти чуть меньше, поэтому не даёт 2.68.
- "Выведет: 3 4 -2 2.67" — неверно: 2.5 округляется до 2, а не до 3 (округление к чётному).
- "Выведет: 2 3 -2 2.67" — неверно: 3.5 округляется до 4, а не до 3.
Выводы и рекомендации
- Python использует округление "к ближайшему чётному" для случаев .5 — это нормальное и предсказуемое поведение.
- Для финансовых и критичных к точности задач не полагайтесь на двоичное float-округление: используйте decimal с десятичной инициализацией через строку.
- Если нужно просто печатать число с нужным количеством знаков и вас устраивает визуальное представление, форматирование строк (f"{x:.2f}") часто подходит, но помните про внутреннюю плавающую точку.