Is there a ceiling equivalent of // operator in Python?

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.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)