Округление до 5 (или другого числа) в Python

162

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

10 -> 10
12 -> 10
13 -> 15
14 -> 15
16 -> 15
18 -> 20
Pydev UA
источник

Ответы:

304

Я не знаю стандартной функции в 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.

Алок Сингхал
источник
3
Если только целые числа и округление вниз, то вы также можете просто сделатьx // base * base
Tjorriemorrie
7
это я параноик , но я предпочитаю использовать floor()и ceil()вместо литья:base * floor(x/base)
user666412
1
@ user666412 math.floorи math.ceilне разрешать использование с пользовательской базой, поэтому предпочтение не имеет значения.
Acumenus
48

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

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

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

CCKx
источник
2
Вы можете использовать: def my_round(x, prec=2, base=0.05): return (base * (np.array(x) / base).round()).round(prec) который также принимает массивы.
саубхик
23

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

>>> 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
АМО-ej1
источник
14

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

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

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

rounded = val - val % 5

Как функция:

def roundint(value, base=5):
    return int(value) - int(value) % int(base)
hgdeoro
источник
Мне нравится этот ответ для округления до ближайшего дробного значения. т.е. если я только хочу приращения 0,25.
Джерси бин
14
def round_to_next5(n):
    return n + (5 - n) % 5
Энди Вонг
источник
9

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
pwdyson
источник
1
+1 за то, что показал нам, что round () может обрабатывать округления до кратных, отличных от 1,0, включая более высокие значения. (Заметьте, однако, что подход со сдвигом битов не будет работать с плавающими, не говоря уже о том, что он гораздо менее читабелен для большинства программистов.)
Питер Хансен
1
@ Питер Хансен спасибо за +1. Нужно иметь int (x) для сдвига битов для работы с поплавками. Согласился, не самый читаемый, и я бы не стал использовать его сам, но мне нравилась «чистота», включающая только 1, а не 2 или 5.
pwdyson
6

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

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

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

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

ArturJ
источник
Пожалуйста, не пытайтесь обойти новые ограничения пользователей, разместив комментарий в качестве ответа. Ограничения существуют по причине . Примите это во внимание в качестве возможной причины, почему и как удаляются некоторые ответы?
Прощай, StackExchange,
4

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

def divround(value, step, barrage):
    result, rest = divmod(value, step)
    return result*step if rest < barrage else (result+1)*step
Кристиан Хаускнехт
источник
так что в этом случае вы используете Divround (значение, 5, 3)? или, может быть, divround (значение 5, 2,5)?
pwdyson
divround (значение 5, 3), точно.
Кристиан Хаускнехт
4

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

>>> 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
Воутер болстерлее
источник
2

В случае, если кому-то нужно «финансовое округление» (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, поскольку он имеет некоторые статистические преимущества (округленные результаты не смещены).

Петр Сейда
источник
2

Для целых чисел и с Python 3:

def divround_down(value, step):
    return value//step*step


def divround_up(value, step):
    return (value+step-1)//step*step

Производство:

>>> [divround_down(x,5) for x in range(20)]
[0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 15, 15, 15, 15, 15]
>>> [divround_up(x,5) for x in range(20)]
[0, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 15, 15, 15, 15, 15, 20, 20, 20, 20]
Сильвен Леру
источник
1

Следующий кратный из 5

Рассмотрим 51 необходимо преобразовать в 55:

code here

mark = 51;
r = 100 - mark;
a = r%5;
new_mark = mark + a;
Виджей
источник
1

Вот мой код C Если я правильно понимаю, должно быть что-то вроде этого;

#include <stdio.h>

int main(){
int number;

printf("Enter number: \n");
scanf("%d" , &number);

if(number%5 == 0)
    printf("It is multiple of 5\n");
else{
    while(number%5 != 0)
        number++;
  printf("%d\n",number);
  }
}

и это также округляет до ближайшего кратного 5 вместо простого округления;

#include <stdio.h>

int main(){
int number;

printf("Enter number: \n");
scanf("%d" , &number);

if(number%5 == 0)
    printf("It is multiple of 5\n");
else{
    while(number%5 != 0)
        if (number%5 < 3)
            number--;
        else
        number++;
  printf("nearest multiple of 5 is: %d\n",number);
  }
}
Эге Мерей
источник
1

Другой способ сделать это (без явных операторов умножения или деления):

def rnd(x, b=5):
    return round(x + min(-(x % b), b - (x % b), key=abs))
cosmic_inquiry
источник
-3

Вы можете «обмануть» int()округление вместо округления, добавив 0.5к числу, которое вы передаете int().

Франциска Зсирос
источник
2
Это на самом деле не отвечает на вопрос
Ури Агасси