Раунд до 5 (або інше число) в Python


162

Чи є вбудована функція, яка може округлитись так:

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

Відповіді:


304

Я не знаю стандартної функції в 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 (", не змінюючи значення параметрів).


2
Ви можете використовувати: def my_round(x, prec=2, base=0.05): return (base * (np.array(x) / base).round()).round(prec) який також приймає нумерові масиви.
saubhik

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

14

Видалення «відпочинку» спрацює:

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

Якщо значення дорівнює цілому числу:

rounded = val - val % 5

Як функція:

def roundint(value, base=5):
    return int(value) - int(value) % int(base)

Мені подобається ця відповідь за округлення до найближчого дробового значення. тобто якщо я хочу лише з кроком 0,25.
jersey bean


9

круглий (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

1
+1, показавши нам, що round () може обробляти округлення до кратних, ніж 1,0, включаючи більш високі значення. (Однак зауважте, що підхід, що змінює біт, не працюватиме з поплавцями, не кажучи вже про те, що він набагато менш читабельний для більшості програмістів.)
Пітер Хансен

1
@Peter Hansen дякую за +1 Потрібно мати int (x) для переміщення біта для роботи з поплавками. Погодився не з найбільш читаним, і я би сам не користувався цим, але мені подобалося, що "чистота" його стосується лише 1-х, а не 2-х чи 5-х.
pwdyson

6

Вибачте, я хотів прокоментувати відповідь Алока Сінгаха, але це не дозволить мені через відсутність репутації = /

У будь-якому випадку ми можемо узагальнити ще один крок і перейти:

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

Це дозволяє нам використовувати не цілі бази, як- .25небудь або будь-яку іншу дробову базу.


Не намагайтеся обійти нові обмеження користувачів, публікуючи коментар як відповідь. Обмеження існують з причини . Враховуйте це як можливу причину Чому і як видаляються деякі відповіді?
Goodbye 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)? чи, можливо, дивінг (значення, 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 (у напрямку до-нескінченності),
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))

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.