Python 将整数四舍五入到下一个百

似乎这个问题已经被问过几百次了(双关语很有趣 =) ,但是我只能找到舍入浮点数的函数。如何四舍五入一个整数,例如: 130 -> 200

117811 次浏览

Try this:

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

If your int is x: x + 100 - x % 100

However, as pointed in comments, this will return 200 if x==100.

If this is not the expected behavior, you can use x + 100*(x%100>0) - x%100

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

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

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

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

Try this:

import math
def ceilm(number,multiple):
'''Returns a float rounded up by a factor of the multiple specified'''
return math.ceil(float(number)/multiple)*multiple

Sample usage:

>>> ceilm(257,5)
260
>>> ceilm(260,5)
260

Warning: Premature optimizations ahead...

Since so many of the answers here do the timing of this I wanted to add another alternative.

Taking @Martin Geisler 's

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

(which i like best for several reasons)

but factoring out the % action

def roundup2(x):
x100= x % 100
return x if x100 == 0 else x + 100 - x100

Yields a ~20% speed improvement over the original

def roundup3(x):
x100 = x % 100
return x if not x100 else x + 100 - x100

Is even better and is ~36% faster then the original

finally I was thinking that I could drop the not operator and change the order of the branches hoping that this would also increase speed but was baffled to find out that it is actually slower dropping back to be only 23% faster then the original.

def roundup4(x):
x100 = x % 100
return x + 100 - x100  if x100 else x




>python -m timeit -s "x = 130" "x if x % 100 == 0 else x + 100 - x % 100"
1000000 loops, best of 3: 0.359 usec per loop


>python -m timeit -s "x = 130" "x100 = x % 100"  "x if x100 == 0 else x + 100 - x100"
1000000 loops, best of 3: 0.287 usec per loop


>python -m timeit -s "x = 130" "x100 = x % 100"  "x if not x100 else x + 100 - x100"
1000000 loops, best of 3: 0.23 usec per loop


>python -m timeit -s "x = 130" "x100 = x % 100"  "x + 100 - x100 if x100 else x"
1000000 loops, best of 3: 0.277 usec per loop

explanations as to why 3 is faster then 4 would be most welcome.

Here is a very simple solution:

next_hundred = x//100*100+100

How does it work?

  1. Perform the integer division by 100 (it basically cuts off the fractional part of the normal division). In this way you obtain the tens of a number. For example: 243//100=2.
  2. Multiply by 100, getting the original number without its tens and ones. For example: 2*100=200.
  3. Add 100 to get the desired result. For example: 200+100=300

Some examples

  • 0...99 rounded to 100
  • 100...199 rounded to 200
  • etc.

A slightly modified approach rounds 1...100 to 100, 101...200 to 200, etc.:

next_hundred = (x-1)//100*100+100

Simply:

round(599, -2)

will give:

600