This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author Vladimir Feinberg
Recipients Nathaniel Manista, Vladimir Feinberg, mark.dickinson, serhiy.storchaka
Date 2022-02-05.17:32:16
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <CAArNnJfs1HmRZpiS0A7h6mbcnUaaO9oFZY=2zb54aghnZVqb=g@mail.gmail.com>
In-reply-to <1644078696.12.0.465068726414.issue46639@roundup.psfhosted.org>
Content
Mark, I will say I'm pretty sympathetic to the feature-bloat avoidance
perspective here, and if the outcome here is to improve docs, that's still
a win, I think.

That said, since this thread will become precedent, and I think
`math.ceildiv` is the exactly-appropriate amount of commitment Lib should
make to the function (not __ceildiv__ and not "just" a doc note), let me
try to give `ceildiv` the strongest legs I can think of before we make a
decision.

1. Not needing an import - I don't find importing such a standard library
as `math` that onerous. We're not adding a new package here, just a
function. This skepticism could be applied to any existing library
function. Even `sys.stdout` needs an import.
2. Natural duck typing - I'll admit, this is pretty nice. But if that's the
argument, I'd expect this to work to its fullest extent. Namely, I'd expect
this to "naturally" work for any ring, and it doesn't. Z/nZ is a common one
and np.uint is a more common one where the identity -(-x // y) = ceildiv(x,
y) does not hold. The benefit of `math.ceildiv` is it'd either support it,
or say it doesn't, but at least it's explicit.
3. Thin end of wedge - A priori, I would put ceildiv as special because of
the "resource coverage" use case I described in my initial bug message. A
posteriori, there's a clear "kink" in the graph of usage here: ceildiv
(3033) <https://github.com/search?l=&q=ceildiv+language%3APython&type=code>,
rounddiv (25)
<https://github.com/search?q=rounddiv+language%3APython&type=code>, roundmod
(7) <https://github.com/search?q=roundmod+language%3APython&type=code>, ceilrem
(0) <https://github.com/search?q=ceilrem+language%3APython&type=code>,
ceildivrem
(0) <https://github.com/search?q=ceildivrem+language%3APython&type=code>.

But most importantly, let me detail what motivated me to post this. I was
working on unit tests for linear algebra code which blocked its operations.
But to not involve a lot of context, I'll provide a similarly-structured
use case. Say we're making a controller for a game engine GUI and need to
figure out how to paint sprites.

```
# sprite_A.py
class A:
  def get_covering_rectangle():
    return self.x, self.y, self.x - (-self.width // GRID_WIDTH), self.y -
(-self.height // GRID_HEIGHT)
```

Especially if I also use `-(-x//y)` elsewhere, this is just asking too much
of the reader. I could leave a comment to the tune of `# Note below is
equivalent to + (-(-x//y)), the ceildiv operator, and this works because x
isn't a uint`. Should I do this at all usage sites? I'd end up factoring
into my own `ceildiv` for clarity, especially if I use this elsewhere, like
a test.

Where should this hand-rolled ceildiv live, if not recreated in everyone's
code? It seems too light to wrap as its own dependency, and we probably
don't want to go down the leftpad
<https://www.theregister.com/2016/03/23/npm_left_pad_chaos/> path. `math`
seems most apt.

On Sat, Feb 5, 2022 at 8:31 AM Mark Dickinson <report@bugs.python.org>
wrote:

>
> Mark Dickinson <dickinsm@gmail.com> added the comment:
>
> I'm not convinced that this deserves to be a math module function. I agree
> that `-(-x // y)`, while simple to write, isn't necessarily obvious. But it
> does have some advantages, like not needing an import, and being naturally
> duck-typed, so that it automatically does the right thing for floats, or
> `fractions.Fraction` objects, or `numpy.int64` objects, or SymPy integers.
> (Not for `Decimal` instances, but that's another story.) Unless we were to
> add a whole __ceildiv__ mechanism, a math module implementation would
> necessarily be limited to integers. (Or perhaps integers and floats.)
>
> There's also the "thin end of the wedge" argument: if ceildiv, why not
> also ceilrem, ceildivrem, rounddiv, roundmod, etc.
>
> The main issue with the `-(-x // y)` spelling seems to be discoverability:
> if everyone knew that this was the right way to spell ceiling division,
> then there wouldn't be a problem. And I'm not convinced that a math.ceildiv
> function would necessarily solve the discoverability problem, either.
>
> So maybe the solution is to advertise the `-(-x // y)` pattern better in
> documentation, for example at the point where floor division is introduced
> in the library reference?
>
> ----------
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <https://bugs.python.org/issue46639>
> _______________________________________
>
History
Date User Action Args
2022-02-05 17:32:17Vladimir Feinbergsetrecipients: + Vladimir Feinberg, mark.dickinson, serhiy.storchaka, Nathaniel Manista
2022-02-05 17:32:17Vladimir Feinberglinkissue46639 messages
2022-02-05 17:32:16Vladimir Feinbergcreate