Round to 5 (or other number) in Python

PythonRounding

Python Problem Overview


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

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

Python Solutions


Solution 1 - Python

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

Solution 2 - Python

For rounding to non-integer values, such as 0.05:

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

I found this useful since I could just do a search and replace in my code to change "round(" to "myround(", without having to change the parameter values.

Solution 3 - Python

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

Solution 4 - Python

Removing the 'rest' would work:

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

If the value is aready an integer:

rounded = val - val % 5

As a function:

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

Solution 5 - Python

def round_to_next5(n):
    return n + (5 - n) % 5

Solution 6 - Python

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

Solution 7 - Python

Sorry, I wanted to comment on Alok Singhai's answer, but it won't let me due to a lack of reputation =/

Anyway, we can generalize one more step and go:

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

This allows us to use non-integer bases, like .25 or any other fractional base.

Solution 8 - Python

Use:

>>> def round_to_nearest(n, m):
        r = n % m
        return n + m - r if r + r >= m else n - r

It does not use multiplication and will not convert from/to floats.

Rounding to the nearest multiple of 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

As you can see, it works for both negative and positive numbers. Ties (e.g. -15 and 15) will always be rounded upwards.

A similar example that rounds to the nearest multiple of 5, demonstrating that it also behaves as expected for a different "base":

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

Solution 9 - Python

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

Solution 10 - Python

Modified version of divround :-)

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

Solution 11 - Python

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]

Solution 12 - Python

Next multiple of 5

Consider 51 needs to be converted to 55:

code here

mark = 51;
r = 100 - mark;
a = r%5;
new_mark = mark + a;

Solution 13 - Python

In case someone needs "financial rounding" (0.5 rounds always up):

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

As per documentation other rounding options are:

> ROUND_CEILING (towards Infinity),
> ROUND_DOWN (towards zero),
> ROUND_FLOOR (towards -Infinity),
> ROUND_HALF_DOWN (to nearest with ties going towards zero),
> ROUND_HALF_EVEN (to nearest with ties going to nearest even integer),
> ROUND_HALF_UP (to nearest with ties going away from zero), or
> ROUND_UP (away from zero).
> ROUND_05UP (away from zero if last digit after rounding towards zero would have been 0 or 5; otherwise towards zero)

By default Python uses ROUND_HALF_EVEN as it has some statistical advantages (the rounded results are not biased).

Solution 14 - Python

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

Solution 15 - Python

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

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

Solution 16 - Python

What about this:

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

Solution 17 - Python

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

Solution 18 - Python

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

Solution 19 - Python

You can “trick” int() into rounding off instead of rounding down by adding 0.5 to the number you pass to int().

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPydev UAView Question on Stackoverflow
Solution 1 - PythonAlok SinghalView Answer on Stackoverflow
Solution 2 - PythonCCKxView Answer on Stackoverflow
Solution 3 - Pythonamo-ej1View Answer on Stackoverflow
Solution 4 - PythonhgdeoroView Answer on Stackoverflow
Solution 5 - PythonAndy WongView Answer on Stackoverflow
Solution 6 - PythonpwdysonView Answer on Stackoverflow
Solution 7 - PythonAkuView Answer on Stackoverflow
Solution 8 - Pythonwouter bolsterleeView Answer on Stackoverflow
Solution 9 - PythonKiriSakowView Answer on Stackoverflow
Solution 10 - PythonChristian HausknechtView Answer on Stackoverflow
Solution 11 - PythonSylvain LerouxView Answer on Stackoverflow
Solution 12 - PythonvijayView Answer on Stackoverflow
Solution 13 - PythonPiotr SiejdaView Answer on Stackoverflow
Solution 14 - Pythoncosmic_inquiryView Answer on Stackoverflow
Solution 15 - PythonDome271View Answer on Stackoverflow
Solution 16 - PythonChristian HausknechtView Answer on Stackoverflow
Solution 17 - PythonEge MereyView Answer on Stackoverflow
Solution 18 - PythonTy PalmView Answer on Stackoverflow
Solution 19 - PythonFranciska ZsirosView Answer on Stackoverflow