207

I found out about the // operator in Python which in Python 3 does division with floor.

Is there an operator which divides with ceil instead? (I know about the / operator which in Python 3 does floating point division.)

Léo Lam
  • 3,870
  • 4
  • 34
  • 44
Cradam
  • 2,282
  • 2
  • 13
  • 8
  • 1
    Important: do you want an int or float result? – smci Jun 25 '15 at 06:36
  • 14
    You should change accepted answer to dlitz's. math.ceil is for floats, it does not work with Python's arbitrary-precision long ints. – endolith May 01 '16 at 17:50
  • 3
    @milllimoose The question is valid, because 1) "ceil division" is also based on "division with modulus", 2) math doesn't really say what's common and what isn't, 3) you need this operation for "continuous bin packing problem", i.e. how many boxes of size $k$ are neeeded to pack $n$ items. – Tomasz Gandor Nov 21 '19 at 04:57

9 Answers9

426

No, but you can use upside-down floor division:¹

def ceildiv(a, b):
    return -(a // -b)

This works because Python's division operator does floor division (unlike in C, where integer division truncates the fractional part).

Here's a demonstration:

>>> from __future__ import division     # for Python 2.x compatibility
>>> import math
>>> def ceildiv(a, b):
...     return -(a // -b)
...
>>> b = 3
>>> for a in range(-7, 8):
...     q1 = math.ceil(a / b)   # a/b is float division
...     q2 = ceildiv(a, b)
...     print("%2d/%d %2d %2d" % (a, b, q1, q2))
...
-7/3 -2 -2
-6/3 -2 -2
-5/3 -1 -1
-4/3 -1 -1
-3/3 -1 -1
-2/3  0  0
-1/3  0  0
 0/3  0  0
 1/3  1  1
 2/3  1  1
 3/3  1  1
 4/3  2  2
 5/3  2  2
 6/3  2  2
 7/3  3  3

Why this instead of math.ceil?

math.ceil(a / b) can quietly produce incorrect results, because it introduces floating-point error. For example:

>>> from __future__ import division     # Python 2.x compat
>>> import math
>>> def ceildiv(a, b):
...     return -(a // -b)
...
>>> x = 2**64
>>> y = 2**48
>>> ceildiv(x, y)
65536
>>> ceildiv(x + 1, y)
65537                       # Correct
>>> math.ceil(x / y)
65536
>>> math.ceil((x + 1) / y)
65536                       # Incorrect!

In general, it's considered good practice to avoid floating-point arithmetic altogether unless you specifically need it. Floating-point math has several tricky edge cases, which tends to introduce bugs if you're not paying close attention. It can also be computationally expensive on small/low-power devices that do not have a hardware FPU.


¹In a previous version of this answer, ceildiv was implemented as return -(-a // b) but it was changed to return -(a // -b) after commenters reported that the latter performs slightly better in benchmarks. That makes sense, because the dividend (a) is typically larger than the divisor (b). Since Python uses arbitrary-precision arithmetic to perform these calculations, computing the unary negation -a would almost always involve equal-or-more work than computing -b.

dlitz
  • 5,679
  • 3
  • 19
  • 13
  • 2
    @apadana I agree this is very smart, but not very readable and hard to maintain! I have decided to import ceil from math so that when one of my colleagues reads my line of code he will understand what it does! – tomcheney Mar 21 '18 at 11:28
  • 3
    @apadana I disagree. The question asked whether there "is" an operator for this "in" Python. Based on the responses, the answer appears to be "no." I'm upvoting dlitz's answer for its usefulness, though. – Ana Nimbus Jul 25 '18 at 22:49
  • 17
    @SlimCheney Toss this method into a documented function and you're good to go. Performance + readability in one sweeping motion. – Samie Bencherif Dec 10 '18 at 10:45
  • 5
    @SamyBencherif: Not just performance + readability, but also correctness for large inputs; floating point has representation limitations, while Python's `int` does not (well, no meaningful ones; on 64 bit Python you're limited to `30 * (2**63 - 1)` bit numbers), and even temporarily converting to `float` can lose information. Compare `math.ceil((1 << 128) / 10)` to `-(-(1 << 128) // 10)`. – ShadowRanger Jan 03 '20 at 14:36
  • 2
    This should just be included in standard library – endolith Feb 04 '20 at 04:11
  • 1
    Should be noted that this method will not work with Decimal objects. – Ernest0x Jun 16 '20 at 18:05
  • This implementation works for `int`, `float` (returns `float`) and `datetime.timedelta` (returns `int`), but may not work for other types depending on their `//` operator behavior (e. g. `decimal.Decimal`, as noted above). So there is no general solution for arbitrary types. – belkka Aug 17 '20 at 18:48
  • 2
    For a compact version: `ceildiv = lambda a, b: -(-a // b)` – Vasco Cansado Carvalho Jul 03 '21 at 19:54
  • @tomcheney, can't you just document your code? It's hard for me to imagine code in which ```-(-a // b)``` is the most complicated expression. – Joe Aug 09 '21 at 13:33
  • This should *really* just be part of the standard math library. https://bugs.python.org/issue46639 https://github.com/python/cpython/issues/90797 – endolith Apr 02 '23 at 14:52
71

There is no operator which divides with ceil. You need to import math and use math.ceil

Machavity
  • 30,841
  • 27
  • 92
  • 100
Charles Salvia
  • 52,325
  • 13
  • 128
  • 140
  • so foobar = math.ceil(foo / bar)? Hmm, I can live with that, don't know of anywhere I wanted to use that, was just curious, thanks – Cradam Feb 11 '13 at 22:51
  • 61
    –1 **do not use**, this will begin to fail for very large integers. Either use a multiple-precision arithmetic library or stay in the integer domain with [this](https://stackoverflow.com/a/17511341/674039) approach. – wim May 30 '17 at 20:21
  • 5
    definitely stay in the integer domain. that's almost guaranteed to be more performant _and_ less of a headache. – Samie Bencherif Dec 10 '18 at 10:44
  • 1
    Note that math.ceil is limited to 53 bits of precision. If you are working with large integers, you may not get exact results. – techkuz Jul 08 '19 at 08:39
63

Solution 1: Convert floor to ceiling with negation

def ceiling_division(n, d):
    return -(n // -d)

Reminiscent of the Penn & Teller levitation trick, this "turns the world upside down (with negation), uses plain floor division (where the ceiling and floor have been swapped), and then turns the world right-side up (with negation again)"

Solution 2: Let divmod() do the work

def ceiling_division(n, d):
    q, r = divmod(n, d)
    return q + bool(r)

The divmod() function gives (a // b, a % b) for integers (this may be less reliable with floats due to round-off error). The step with bool(r) adds one to the quotient whenever there is a non-zero remainder.

Solution 3: Adjust the numerator before the division

def ceiling_division(n, d):
    return (n + d - 1) // d

Translate the numerator upwards so that floor division rounds down to the intended ceiling. Note, this only works for integers.

Solution 4: Convert to floats to use math.ceil()

def ceiling_division(n, d):
    return math.ceil(n / d)

The math.ceil() code is easy to understand, but it converts from ints to floats and back. This isn't very fast and it may have rounding issues. Also, it relies on Python 3 semantics where "true division" produces a float and where the ceil() function returns an integer.

Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
  • 3
    In quick tests, #1 is the fastest here, even compared to `-(-a // b)` o_O – endolith Feb 04 '20 at 05:00
  • Confirming here that `-(a // -b)` is faster than `-(-a // b)`, at least when timing toy examples with `python -m timeit ...` – Jasha Jul 31 '20 at 22:40
  • @Jasha, any idea how one could be faster than the other? Are your tests symmetric, in that for every case of the form ```a=x, b=y``` there is a case of the form ```a=y, b=x``` (excluding of course, ```b=0```)? – Joe Aug 09 '21 at 13:37
  • @Joe Sorry, I don't remember :) – Jasha Aug 12 '21 at 21:57
32

You could do (x + (d-1)) // d when dividing x by d, e.g. (x + 4) // 5.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
poke
  • 369,085
  • 72
  • 557
  • 602
  • 3
    This is the classic method I've used forever. Doesn't work for negative divisors though. – Mark Ransom Jul 08 '13 at 16:20
  • It produces the [same result](https://repl.it/FZGd/5) as `math.ceil()`. – Abhijeet Jan 30 '17 at 05:54
  • 5
    @Abhijeet Yes, that's what the question asks. Except it works better for big integers above `sys.float_info.max`, and it doesn't require an import. – Artyer May 10 '17 at 19:01
24

You can always just do it inline as well

((foo - 1) // bar) + 1

In python3, this is just shy of an order of magnitude faster than forcing the float division and calling ceil(), provided you care about the speed. Which you shouldn't, unless you've proven through usage that you need to.

>>> timeit.timeit("((5 - 1) // 4) + 1", number = 100000000)
1.7249219375662506
>>> timeit.timeit("ceil(5/4)", setup="from math import ceil", number = 100000000)
12.096064013894647
Travis Griggs
  • 21,522
  • 19
  • 91
  • 167
  • just ran those tests myself I get about 12.5 seconds, ehrm, why wouldn't I care about speed when it is such a huge speed difference? – Cradam Feb 11 '13 at 23:17
  • 4
    @Cradam Note that he's using doing 100 million calls (`number=100000000`). Per single call, the difference is pretty insignificant. – Rushy Panchal Feb 11 '13 at 23:19
  • 4
    Because code clarity trumps all. Clarity is objective in this case probably. But you should always make readable/maintainable first. When, and only when, you've discovered a performance checkpoint, do you get to break the rules. Modern machines are so fast, and so often all of the other stuff your program is doing renders this kind of difference lost in the noise. – Travis Griggs Feb 11 '13 at 23:26
  • 6
    @TravisGriggs using integer math instead of floating point math isn't just for speed. For large enough integers float math gives the wrong answer – endolith Mar 23 '16 at 01:47
  • @endolith, you seem to be kind of intent on this, adding this comment to multiple answers. I'm not sure there is a "works" for negative divisors because the rules of modulo/remainder division with negative numbers varies. And what to do with a ceiling operator then gets interesting when one crosses the zero line. Does floor move towards zero. The only place this answer doesn't "work" is when both foo and bar are negative. – Travis Griggs Feb 04 '20 at 22:29
  • 1
    If `foo = -8` and `bar = -4`, for example, the answer should be 2, not 3, just like `-8 // -4`. Python floor division is defined as ["that of mathematical division with the ‘floor’ function applied to the result"](https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations) and ceiling division is the same thing but with `ceil()` instead of `floor()`. – endolith Feb 05 '20 at 02:07
  • nice answer! I use it as a lambda function= ` c_int = lambda n, d : ((n - 1) // d) + 1` – meduz Nov 05 '20 at 14:21
8

Note that math.ceil is limited to 53 bits of precision. If you are working with large integers, you may not get exact results.

The gmpy2 libary provides a c_div function which uses ceiling rounding.

Disclaimer: I maintain gmpy2.

casevh
  • 11,093
  • 1
  • 24
  • 35
  • 3
    This package would be useful if I was doing something heavily mathematics or science orientated, I prefer the answer which uses core libraries though. I am giving an upvote though as it is a useful answer – Cradam Feb 12 '13 at 13:38
  • Wow, can confirm. `python2 -c 'from math import ceil;assert ceil(11520000000000000102.9)==11520000000000000000'` (as well as substituting `python3`) BOTH are `True` – JamesTheAwesomeDude Jul 19 '18 at 14:39
1

You can use -(-a//b) or math.ceil(a/b) from math for ceiling division.

Ocean_DA
  • 19
  • 2
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 05 '22 at 06:19
-1

If you want to celling upto multiple off a number. it works like we have Math.celling in excel.

def excel_celling(number=None, multiple_off=None):
    quotient = number // multiple_off
    reminder = number % multiple_off
    celling_value = quotient * multiple_off + (multiple_off, 0)[reminder==0]
    return int(celling_value)


assert excel_celling(99.99, 100) == 100, "True"
print(excel_celling(99.99, 100) , 100)
assert excel_celling(1, 100) == 100, "True"
print(excel_celling(1, 100),100)
assert excel_celling(99, 100) == 100, "True"
print(excel_celling(99, 100),100)
assert excel_celling(90, 100) == 100, "True"
print(excel_celling(90, 100),100)
assert excel_celling(101, 100) == 200, "True"
print(excel_celling(101, 100),200)
assert excel_celling(199, 100) == 200, "True"
print(excel_celling(199, 100),200)
assert excel_celling(199.99, 100) == 200, "True"
print(excel_celling(199.99, 100),200)
assert excel_celling(200, 100) == 200, "True"
print(excel_celling(200, 100),200)

Results

100 100

100 100

100 100

100 100

200 200

200 200

200 200

200 200

Arpan Saini
  • 4,623
  • 1
  • 42
  • 50
-12

Simple solution: a // b + 1