round в Python: .5 → четное и проблема 2.675

round в Python: .5 → четное и проблема 2.675

@python_quiz

Разберем этот квиз

Код квиза:

python

Вывод:

Коротко о сути

Два разных явления объясняют этот результат:

  • При значениях вида 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.

Наглядный пример:

python

Такое поведение помогает снижать систематическую ошибку при суммарном округлении (статистически более нейтральное).

Почему round(2.675, 2) даёт 2.67

Число 2.675 в десятичном виде не представимо точно в формате IEEE 754 double. В памяти оно хранится как значение чуть меньше 2.675 (примерно 2.6749999999999998). Это видно из представления:

python

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

python

Обратите внимание: 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}") часто подходит, но помните про внутреннюю плавающую точку.

Report Page