← Все вопросы

Как округлить число в Python до нужного количества знаков?

Задан 13 месяцев назад842 просмотров2 ответа
10

Нужно округлить дробное число до 2 знаков после запятой. Использую round(), но иногда получаю странности типа round(2.675, 2) даёт 2.67, а не 2.68. Почему так и как округлить правильно для денег?

2 ответа

15
✓ Принятый ответ — помог автору

Базово округляет функция round(число, знаки):

round(3.14159, 2)   # 3.14
round(2.5)          # 2  (внимание!)
round(123.456, 0)   # 123.0
round(1234, -2)     # 1200 — округление до сотен

Теперь про два сюрприза.

Сюрприз 1 — банковское округление. round округляет «к ближайшему чётному», поэтому round(2.5) это 2, а round(3.5) это 4. Это сделано, чтобы не накапливалась систематическая ошибка при суммировании.

Сюрприз 2 — round(2.675, 2) даёт 2.67. Это не баг round, а особенность дробных чисел: 2.675 в двоичной системе хранится как чуть-чуть меньше 2.675, и округляется вниз. Так работает плавающая точка во всех языках.

Для денег не используйте float и round — берите Decimal, который считает точно в десятичной системе:

from decimal import Decimal, ROUND_HALF_UP

price = Decimal('2.675')
print(price.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP))  # 2.68

Обратите внимание — Decimal создают из строки '2.675', а не из float, иначе неточность float попадёт внутрь.

Если точность не критична (вывод на экран), часто проще округлить при форматировании: f'{x:.2f}' — это тоже округление до 2 знаков, но результат уже строка.

5

Если нужно именно «как в школе» — половинки всегда вверх — а тянуть Decimal не хочется, для положительных чисел сработает приём с математикой:

import math
def round_half_up(x, n=0):
    factor = 10 ** n
    return math.floor(x * factor + 0.5) / factor

Но помните: из-за всё той же плавающей точки идеальной точности это не даёт. Для финансов единственный надёжный путь — Decimal. Для отображения чисел пользователю обычного round или f'{x:.2f}' почти всегда достаточно.

Ваш ответ

Войдите, чтобы ответить на вопрос.