Округление до 5 (или другого числа) в Python - PullRequest
139 голосов
/ 16 февраля 2010

Есть ли встроенная функция, которая может округляться следующим образом?

10 -> 10
12 -> 10
13 -> 15
14 -> 15
16 -> 15
18 -> 20

Ответы [ 14 ]

250 голосов
/ 16 февраля 2010

Я не знаю стандартной функции в Python, но это работает для меня:

Python 2

def myround(x, base=5):
    return int(base * round(float(x)/base))

Python3

def myround(x, base=5):
    return base * round(x/base)

Легко понять, почему работает выше. Вы хотите убедиться, что ваше число, деленное на 5, является целым, правильно округленным. Итак, сначала мы делаем именно это (round(float(x)/5), где float требуется только в Python2), а затем, поскольку мы делим на 5, мы также умножаем на 5. Окончательное преобразование в int происходит потому, что round() возвращает значение с плавающей точкой в ​​Python 2.

Я сделал функцию более общей, задав ей параметр base, по умолчанию 5.

40 голосов
/ 07 сентября 2013

Для округления до нецелых значений, таких как 0,05:

def myround(x, prec=2, base=.05):
  return round(base * round(float(x)/base),prec)

Я нашел это полезным, поскольку я мог просто выполнить поиск и заменить в своем коде, чтобы изменить «round (» на «myround (»), не меняя значения параметров.

19 голосов
/ 16 февраля 2010

Это просто вопрос масштабирования

>>> a=[10,11,12,13,14,15,16,17,18,19,20]
>>> for b in a:
...     int(round(b/5.0)*5.0)
... 
10
10
10
15
15
15
15
15
20
20
20
12 голосов
/ 10 сентября 2012

Удаление «остальных» будет работать:

rounded = int(val) - int(val) % 5

Если значение является целым числом:

rounded = val - val % 5

Как функция:

def roundint(value, base=5):
    return int(value) - int(value) % int(base)
7 голосов
/ 27 февраля 2016
def round_to_next5(n):
    return n + (5 - n) % 5
6 голосов
/ 16 февраля 2010

round (x [, n]): значения округляются до ближайшего кратного 10 от степени минус n. Так что, если n отрицательно ...

def round5(x):
    return int(round(x*2, -1)) / 2

Поскольку 10 = 5 * 2, вы можете использовать целочисленное деление и умножение с 2, а не деление с плавающей запятой и умножение с 5,0. Не так уж это важно, если только вы не любите сдвигать бит

def round5(x):
    return int(round(x << 1, -1)) >> 1
4 голосов
/ 28 августа 2014

Извините, я хотел прокомментировать ответ Алока Сингхая, но он не позволит мне из-за отсутствия репутации = /

В любом случае, мы можем обобщить еще один шаг и пойти:

def myround(x, base=5):
    return base * round(float(x) / base)

Это позволяет нам использовать нецелые основания, такие как .25 или любую другую дробную базу.

3 голосов
/ 16 февраля 2010

Модифицированная версия divround: -)

def divround(value, step, barrage):
    result, rest = divmod(value, step)
    return result*step if rest < barrage else (result+1)*step
2 голосов
/ 24 июля 2015

Использование:

>>> from __future__ import division   # This is only needed on Python 2
>>> def round_to_nearest(n, m):
        r = n % m
        return n + m - r if r + r >= m else n - r

...

Он не использует умножение и не будет преобразовывать из / в числа с плавающей запятой.

Округление до ближайшего кратного 10:

>>> for n in range(-21, 30, 3): print('{:3d}  =>  {:3d}'.format(n, round_to_nearest(n, 10)))
-21  =>  -20
-18  =>  -20
-15  =>  -10
-12  =>  -10
 -9  =>  -10
 -6  =>  -10
 -3  =>    0
  0  =>    0
  3  =>    0
  6  =>   10
  9  =>   10
 12  =>   10
 15  =>   20
 18  =>   20
 21  =>   20
 24  =>   20
 27  =>   30

Как видите, он работает как для отрицательных, так и для положительных чисел. Галстуки (например, -15 и 15) всегда будут округлены вверх.

Аналогичный пример, который округляет до ближайшего кратного 5, демонстрируя, что он также ведет себя, как и ожидалось, для другой "базы":

>>> for n in range(-21, 30, 3): print('{:3d}  =>  {:3d}'.format(n, round_to_nearest(n, 5)))
-21  =>  -20
-18  =>  -20
-15  =>  -15
-12  =>  -10
 -9  =>  -10
 -6  =>   -5
 -3  =>   -5
  0  =>    0
  3  =>    5
  6  =>    5
  9  =>   10
 12  =>   10
 15  =>   15
 18  =>   20
 21  =>   20
 24  =>   25
 27  =>   25
1 голос
/ 07 апреля 2017

В случае, если кому-то нужно «финансовое округление» (всегда на 0,5 раунда):

def myround(x, base=5):
    roundcontext = decimal.Context(rounding=decimal.ROUND_HALF_UP)
    decimal.setcontext(roundcontext)
    return int(base *float(decimal.Decimal(x/base).quantize(decimal.Decimal('0'))))

В соответствии с документацией другие варианты округления:

ROUND_CEILING (к бесконечности),
ROUND_DOWN (к нулю),
ROUND_FLOOR (в направлении -Infinity),
ROUND_HALF_DOWN (до ближайшей связи, идущей к нулю),
ROUND_HALF_EVEN (до ближайшей связи, идущей до ближайшего четного целого),
ROUND_HALF_UP (до ближайшей связи, уходящей от нуля), или
ROUND_UP (от нуля).
ROUND_05UP (от нуля, если последняя цифра после округления до нуля была бы 0 или 5; в противном случае до нуля)

По умолчанию Python использует ROUND_HALF_EVEN, поскольку он имеет некоторые статистические преимущества (округленные результаты не смещены).

...