Today I learned how to do ceiling division in Python just with //
.
//
I recently published a tweet telling people about the floor division operator in Python, //
:
Are you familiar with the `//` operator in Python 🐍?
— Rodrigo 🐍📝 (@mathsppblog) September 14, 2021
`//` is the “floor division” operation, which is equivalent to dividing and then rounding down.
`q = n // m` is always an integer, and the value of `q` is equivalent to `q = floor(n / m)`.
How many years fit in 10_000 days? pic.twitter.com/ecRQoz3qkM
This operator is equivalent to doing regular division and then flooring down:
>>> # How many years in 10_000 days?
>>> from math import floor; floor(10_000 / 365)
27
>>> 10_000 // 365
27
Then, someone asked if Python also had a built-in for ceiling division, that is, an operator that divided the operands and then rounded up.
While there is no direct built-in operator for that, someone replied saying that we can use a couple of minus signs and floor division to do that.
Ceiling division with a
and b
would be equivalent to ceil(a / b)
.
And they showed that we can do it with -(-a // b)
:
>>> from math import ceil
>>> a, b = 10, 3
>>> ceil(a / b)
4
>>> -(-a // b)
4
Why does this work?
floor
rounds down and ceil
rounds up.
By using -a
in the division, it's as if you flip a
upside down,
so “its ceiling is now on the floor”, so you can use -a // b
.
Then, you just need to put everything back in place,
using a final negation: -(-a // b)
.
At first, I thought this would fail for some combination of positive/negative values for a
and b
,
but it most certainly doesn't.
For one, the explanation works regardless of the sign of a
and/or b
.
Secondly, one can always test it:
>>> for a, b in [(10, 3), (10, -3), (-10, 3), (-10, -3)]:
... assert ceil(a / b) == -(-a // b)
...
>>>
Here's the original tweet that taught me this:
You can do ceiling division with '//' and some unary '-' signs, since '//' truncates to the next *lowest* number. If the divisor is negative, that means it goes to the next "most-negative" number, which, when negated, is actually "truncating up". pic.twitter.com/uAQmJJbYhw
— Paul McGuire - pyparsing guy (@ptmcguire) September 15, 2021
+35 chapters. +400 pages. Hundreds of examples. Over 30,000 readers!
My book “Pydon'ts” teaches you how to write elegant, expressive, and Pythonic code, to help you become a better developer. >>> Download it here 🐍🚀.