Python round up integer to next hundred

103,753

Solution 1

Rounding is typically done on floating point numbers, and here there are three basic functions you should know: round (rounds to the nearest integer), math.floor (always rounds down), and math.ceil (always rounds up).

You ask about integers and rounding up to hundreds, but we can still use math.ceil as long as your numbers smaller than 253. To use math.ceil, we just divide by 100 first, round up, and multiply with 100 afterwards:

>>> import math
>>> def roundup(x):
...     return int(math.ceil(x / 100.0)) * 100
... 
>>> roundup(100)
100
>>> roundup(101)
200

Dividing by 100 first and multiply with 100 afterwards "shifts" two decimal places to the right and left so that math.ceil works on the hundreds. You could use 10**n instead of 100 if you want to round to tens (n = 1), thousands (n = 3), etc.

An alternative way to do this is to avoid floating point numbers (they have limited precision) and instead use integers only. Integers have arbitrary precision in Python, so this lets you round numbers of any size. The rule for rounding is simple: find the remainder after division with 100, and add 100 minus this remainder if it's non-zero:

>>> def roundup(x):
...     return x if x % 100 == 0 else x + 100 - x % 100

This works for numbers of any size:

>>> roundup(100)
100
>>> roundup(130)
200
>>> roundup(1234567891234567891)
1234567891234567900L

I did a mini-benchmark of the two solutions:

$ python -m timeit -s 'import math' -s 'x = 130' 'int(math.ceil(x/100.0)) * 100'
1000000 loops, best of 3: 0.364 usec per loop
$ python -m timeit -s 'x = 130' 'x if x % 100 == 0 else x + 100 - x % 100'
10000000 loops, best of 3: 0.162 usec per loop

The pure integer solution is faster by a factor of two compared to the math.ceil solution.

Thomas proposed an integer based solution that is identical to the one I have above, except that it uses a trick by multiplying Boolean values. It is interesting to see that there is no speed advantage of writing the code this way:

$ python -m timeit -s 'x = 130' 'x + 100*(x%100>0) - x%100'
10000000 loops, best of 3: 0.167 usec per loop

As a final remark, let me also note, that if you had wanted to round 101–149 to 100 and round 150–199 to 200, e.g., round to the nearest hundred, then the built-in round function can do that for you:

>>> int(round(130, -2))
100
>>> int(round(170, -2))
200

Solution 2

This is a late answer, but there's a simple solution that combines the best aspects of the existing answers: the next multiple of 100 up from x is x - x % -100 (or if you prefer, x + (-x) % 100).

>>> x = 130
>>> x -= x % -100  # Round x up to next multiple of 100.
>>> x
200

This is fast and simple, gives correct results for any integer x (like John Machin's answer) and also gives reasonable-ish results (modulo the usual caveats about floating-point representation) if x is a float (like Martin Geisler's answer).

>>> x = 0.1
>>> x -= x % -100
>>> x
100.0

Solution 3

Try this:

int(round(130 + 49, -2))

Solution 4

Here's a general way of rounding up to the nearest multiple of any positive integer:

def roundUpToMultiple(number, multiple):
    num = number + (multiple - 1)
    return num - (num % multiple)

Sample usage:

>>> roundUpToMultiple(101, 100)
200
>>> roundUpToMultiple(654, 321)
963

Solution 5

For a non-negative, b positive, both integers:

>>> rup = lambda a, b: (a + b - 1) // b * b
>>> [(x, rup(x, 100)) for x in (199, 200, 201)]
[(199, 200), (200, 200), (201, 300)]

Update The currently-accepted answer falls apart with integers such that float(x) / float(y) can't be accurately represented as a float. See this code:

import math

def geisler(x, y): return int(math.ceil(x / float(y))) * y

def orozco(x, y): return x + y * (x % y > 0) - x % y

def machin(x, y): return (x + y - 1) // y * y

for m, n in (
    (123456789123456789, 100),
    (1234567891234567891, 100),
    (12345678912345678912, 100),
    ):
    print; print m, "m"; print n, "n"
    for func in (geissler, orozco, machin):
        print func(m, n), func.__name__

Output:

123456789123456789 m
100 n
123456789123456800 geisler
123456789123456800 orozco
123456789123456800 machin

1234567891234567891 m
100 n
1234567891234568000 geisler <<<=== wrong
1234567891234567900 orozco
1234567891234567900 machin

12345678912345678912 m
100 n
12345678912345680000 geisler <<<=== wrong
12345678912345679000 orozco
12345678912345679000 machin

And here are some timings:

>\python27\python -m timeit -s "import math;x =130" "int(math.ceil(x/100.0))*100"
1000000 loops, best of 3: 0.342 usec per loop

>\python27\python -m timeit -s "x = 130" "x + 100 * (x % 100 > 0) - x % 100"
10000000 loops, best of 3: 0.151 usec per loop

>\python27\python -m timeit -s "x = 100" "(x + 99) // 100 * 100"
10000000 loops, best of 3: 0.0903 usec per loop
Share:
103,753
userBG
Author by

userBG

I enjoy programming in Python &amp; JavaScript.

Updated on May 18, 2021

Comments

  • userBG
    userBG almost 3 years

    Seems that should have already been asked hundreds (pun are fun =) of times but i can only find function for rounding floats. How do I round up an integer, for example: 130 -> 200 ?

  • Thomas Orozco
    Thomas Orozco over 12 years
    You might want to use the other solutions if you don't like magic numbers though. If you're concerned with performance, this however runs faster.
  • userBG
    userBG over 12 years
    I'm not doing a normal rounding here, if I were yes, I would use round()
  • userBG
    userBG over 12 years
    Yes, 100 should remain not be rounded up but if that would make the formula too complicated, I can prevent that using code, no bigy
  • Martin Geisler
    Martin Geisler over 12 years
    @ofko: right, you want to round up. The math.ceil is the canonical way to do that — dividing and multiplying by 100 is the canonical way to make round, ceil, and floor work on hundreds.
  • Thomas Orozco
    Thomas Orozco over 12 years
    Well the other version solves this, as it includes the check before adding 100! If this adresses your need, don't forget to accept! :)
  • Martin Geisler
    Martin Geisler over 12 years
    I'm sorry, but I find this code very un-pythonic. Yes, a bool has a numeric value, so yes, you can multiply with a boolean expression. But the other solutions are clearer.
  • Thomas Orozco
    Thomas Orozco over 12 years
    Well, I indeed pointed out that other code could be preferred if performance is not a key parameter.
  • Martin Geisler
    Martin Geisler over 12 years
    @ThomasOrozco: you're right, your solution is twice as fast at the one I proposed.
  • userBG
    userBG over 12 years
    After the recent edits, it now makes sense to accept this answer.
  • John Machin
    John Machin over 12 years
    -1 This approach may be "canonical" with floats, but it FAILS with large integers. See my answer for details. The OP specifically asked for integers and expressed no upper bound on the size of numbers.
  • Martin Geisler
    Martin Geisler over 12 years
    @JohnMachin: The downvote is for questions that "are not useful" and I fail to see why this simple and straight-forward answer is not useful. Infact, the OP marked it as accepted, so it is useful. Further, when someone needs help to round 130 to 200, then I think it's stretching it a bit to complain about not rounding 1234567891234567891 correctly. You're right that there's limited precission in float compared to long (of course!), but for most practical situations a float is plenty big.
  • John Machin
    John Machin over 12 years
    One can reliably infer nothing from acceptance of an answer. One can reliably infer nothing from a single example input value. The question did ask for integers, not floats. Your answer still leads off with floats and contains the "canonical" waffle. Your new integer only solution is at least correct but is baroque and slow.
  • Martin Geisler
    Martin Geisler over 12 years
    @JohnMachin: you really take offense to me calling math.ceil the canonical way to round up, don't you? I've taken it out now and I hope you like the introduction better.
  • John Machin
    John Machin over 12 years
    You need to look up "take offence". I have not taken offence. I am not offended. My point is that "canonical" merely means "recommended by some prescribing authority" or "usual"; it doesn't automatically mean "good idea". New introduction: (1) it STILL starts off with floats! (2) round does not round to the nearest integer; it rounds to the nearest integral multiple of 10 ** (-second_arg); the behaviour of round() changed between 2.X and 3.X; round should be mentioned in this context only to warn against its use.
  • Martin Geisler
    Martin Geisler over 12 years
    @JohnMachin: Okay, I'm glad you're not offended. I was not aware of the change to round in Python 3, thanks for pointing that out. I mention math.ceil and round since I feel that they are the first two functions you should think of them you're asked to round something. I'm trying to give the OP building blocks so that he can solve rounding tasks in the future.
  • mic_e
    mic_e over 9 years
    equivalent, shorter method: lambda number, multiple: multiple * (1 + (number - 1) // multiple)
  • tagoma
    tagoma about 7 years
    your solution is as as fast as Martin's but notation is shorter. thanks. %timeit 'x = 110' 'x -= x % -100' # 100000000 loops, best of 3: 9.37 ns per loop VS %timeit 'x = 110' 'x + 100*(x%100>0) - x%100' #100000000 loops, best of 3: 9.38 ns per loop
  • epeleg
    epeleg over 6 years
    I know the OP was about rounding an integer - but I wanted to point out that you would try to use those 3 options on (0.5,10) which I would expect to return 10 then the first two methods (geisler & orozco) return 10 as expected while machin returns 0
  • Tim Richardson
    Tim Richardson over 3 years
    why int() ? type(round(999,-2)) is int (python 3.8)
  • Tim
    Tim over 3 years
    This doesn't always round up though, which is what the question asked.
  • George Adams
    George Adams over 2 years
    Note: To always round down, it is x -= x % +100