Round to 5 (or other number) in Python

Viewed 182441

Is there a built-in function that can round like the following?

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

I don't know of a standard function in Python, but this works for me:

Python 3

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

It is easy to see why the above works. You want to make sure that your number divided by 5 is an integer, correctly rounded. So, we first do exactly that (round(x/5)), and then since we divided by 5, we multiply by 5 as well.

I made the function more generic by giving it a base parameter, defaulting to 5.

Python 2

In Python 2, float(x) would be needed to ensure that / does floating-point division, and a final conversion to int is needed because round() returns a floating-point value in Python 2.

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

It's just a matter of scaling

>>> 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

round(x[, n]): values are rounded to the closest multiple of 10 to the power minus n. So if n is negative...

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

Since 10 = 5 * 2, you can use integer division and multiplication with 2, rather than float division and multiplication with 5.0. Not that that matters much, unless you like bit shifting

def round5(x):
    return int(round(x << 1, -1)) >> 1
def round_up_to_base(x, base=10):
    return x + (base - x) % base

def round_down_to_base(x, base=10):
    return x - (x % base)

which gives

for base=5:

>>> [i for i in range(20)]
[0, 1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> [round_down_to_base(x=i, base=5) for i in range(20)]
[0, 0,  0,  0,  0,  5,  5,  5,  5,  5,  10, 10, 10, 10, 10, 15, 15, 15, 15, 15]

>>> [round_up_to_base(x=i, base=5) for i in range(20)]
[0, 5,  5,  5,  5,  5,  10, 10, 10, 10, 10, 15, 15, 15, 15, 15, 20, 20, 20, 20]

for base=10:

>>> [i for i in range(20)]
[0, 1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> [round_down_to_base(x=i, base=10) for i in range(20)]
[0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10]

>>> [round_up_to_base(x=i, base=10) for i in range(20)]
[0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 20, 20, 20, 20]

tested in Python 3.7.9

Modified version of divround :-)

def divround(value, step, barrage):
    result, rest = divmod(value, step)
    return result*step if rest < barrage else (result+1)*step

For integers and with Python 3:

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


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

Producing:

>>> [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]

Another way to do this (without explicit multiplication or division operators):

def rnd(x, b=5):
    return round(x + min(-(x % b), b - (x % b), key=abs))

No one actually wrote this yet I guess but you can do:

round(12, -1) --> 10
round(18, -1) --> 20

What about this:

 def divround(value, step):
     return divmod(value, step)[0] * step

I needed to round down to the preceding 5.

Example 16 rounds down to 15 or 19 rounds down to 15

Here's the code used

    def myround(x,segment):
        preRound = x / segment
        roundNum = int(preRound)
        segVal = segment * roundNum
        return segVal

Here is my C code. If I understand it correctly, it should supposed to be something like this;

#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);
  }
}

and this also rounds to nearest multiple of 5 instead of just rounding up;

#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);
  }
}

An addition to accepted answer, to specify rounding up or down to nearest 5-or-whatever

import math

def my_round(x, base, down = True):
    return base * math.floor(x/base) + (not down) * base

A solution that works only with ints (it accepts floats, but the rounding behaves as if the decimal component doesn't exist), but unlike any solution relying on temporary conversion to float (all the math.floor/math.ceil-based solutions, all the solutions using /, most solutions using round), it works for arbitrarily huge int inputs, never losing precision, never raising exceptions or resulting in infinity values.

It's an adaptation of the simplest solution for rounding down to the next lower multiple of a number:

def round_to_nearest(num, base=5):
    num += base // 2
    return num - (num % base)

The round down recipe it's based on is just:

def round_down(num, base=5):
    return num - (num % base)

the only change is that you add half the base to the number ahead of time so it rounds to nearest. With exact midpoint values, only possible with even bases, rounding up, so round_to_nearest(3, 6) will round to 6 rather than 0, while round_to_nearest(-3, 6) will round to 0 rather than -6. If you prefer midpoint values round down, you can change the first line to num += (base - 1) // 2.

Related