# Division with different rounding

**URL:** <https://discuss.python.org/t/division-with-different-rounding/107587>\
**Category:** Ideas\
**Created:** [May 31, 2026, 4:03am UTC](https://discuss.python.org/t/division-with-different-rounding/107587 "2026-05-31T04:03:11Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![skirpichev](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/skirpichev/32/10996_2.png) [@skirpichev](https://discuss.python.org/u/skirpichev)\
**Post date:** [May 31, 2026, 4:03am UTC](https://discuss.python.org/t/division-with-different-rounding/107587/1 "2026-05-31T04:03:11Z")

</div>

It’s a restart of relatively recent thread, [asking for integer ceil division](https://discuss.python.org/t/integer-ceiling-divide/91269). We have a similar request for round-to-nearest case (issue [#76159](https://github.com/python/cpython/issues/76159)).

One possible approach is to add several functions to the math.integer module. For instance, the gmpy2 module has [c\_div()](https://gmpy2.readthedocs.io/en/latest/mpz.html#gmpy2.c_div), [c\_mod()](https://gmpy2.readthedocs.io/en/latest/mpz.html#gmpy2.c_mod) and [c\_divmod()](https://gmpy2.readthedocs.io/en/latest/mpz.html#gmpy2.c_divmod) for division with rounding toward +Inf (ceiling rounding) and similar sets of functions for floor rounding and for rounding toward 0 (there is no case for round-to-nearest mode).

Alternatively, we could use few functions (say, `math.integer.div()`, etc) with optional keyword argument, say `rounding` or `round`, to specify the rounding mode. Such option could be useful for some other integer functions, like `isqrt()`, see e.g. issue [#90345](https://github.com/python/cpython/issues/90345).

On another hand, maybe different rounding modes could be helpful for non-integer objects too (like `datetime.timedelta`) in the context of integer division (see [use case](https://github.com/python/cpython/issues/90797#issuecomment-3492552891)). In this case we might consider to add a new keyword argument to `divmod()`/` __divmod__ ()` functions.

---

<div class="post-metadata">

**Author:** ![jb2170](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jb2170/32/24298_2.png) [@jb2170](https://discuss.python.org/u/jb2170)\
**Post date:** [June 1, 2026, 2:05am UTC](https://discuss.python.org/t/division-with-different-rounding/107587/2 "2026-06-01T02:05:02Z")

</div>

I’m on board with `ceildiv`!

I’ve replied in [\>\>91269](https://discuss.python.org/t/integer-ceiling-divide/91269/27) to keep all the messages / quotes / replies together because I don’t see a rule against necroposting 😅

---

<div class="post-metadata">

**Author:** ![skirpichev](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/skirpichev/32/10996_2.png) [@skirpichev](https://discuss.python.org/u/skirpichev)\
**Post date:** [June 1, 2026, 2:38am UTC](https://discuss.python.org/t/division-with-different-rounding/107587/3 "2026-06-01T02:38:15Z")

</div>

> [@jb2170](#):
>
> I’m on board with `ceildiv`!

I think that all rounding modes, at least mentioned in the C standard, do make sense in some applications. The CPython internals reinvented several times division with round-to-nearest rounding, see referenced issue.

But I doubt that bunch of new functions in the math.integer module is a good idea. Rounding also make sense for some other integer functions, not just division. Other than mentioned: integer logarithm or nth root.

BTW, I proposed a patch for adding [isqrt\_rem()](https://github.com/python/cpython/pull/150224), based on the discussion in issue thread. But Raymods idea seems clearer for me.

> [@jb2170](#):
>
> I don’t see a rule against necroposting

It’s still discouraged here. Just undefined.

---

<div class="post-metadata">

**Author:** ![vstinner](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/vstinner/32/15130_2.png) [@vstinner](https://discuss.python.org/u/vstinner)\
**Post date:** [June 1, 2026, 3:15pm UTC](https://discuss.python.org/t/division-with-different-rounding/107587/4 "2026-06-01T15:15:21Z")

</div>

I’m not sure if it’s relevant for the `math` / `math.integer` API, but FYI Python has an internal [`<pycore_time.h>`](https://github.com/python/cpython/blob/e8034dd841808416e243a4b2f8e08f0edf9caff3/Include/internal/pycore_time.h) API which takes a rounding argument:

```c
typedef enum {
    // Round towards minus infinity (-inf).
    // For example, used to read a clock.
    _PyTime_ROUND_FLOOR=0,

    // Round towards infinity (+inf).
    // For example, used for timeout to wait "at least" N seconds.
    _PyTime_ROUND_CEILING=1,

    // Round to nearest with ties going to nearest even integer.
    // For example, used to round from a Python float.
    _PyTime_ROUND_HALF_EVEN=2,

    // Round away from zero
    // For example, used for timeout. _PyTime_ROUND_CEILING rounds
    // -1e-9 to 0 milliseconds which causes bpo-31786 issue.
    // _PyTime_ROUND_UP rounds -1e-9 to -1 millisecond which keeps
    // the timeout sign as expected. select.poll(timeout) must block
    // for negative values.
    _PyTime_ROUND_UP=3,

    // _PyTime_ROUND_TIMEOUT (an alias for _PyTime_ROUND_UP) should be
    // used for timeouts.
    _PyTime_ROUND_TIMEOUT = _PyTime_ROUND_UP
} _PyTime_round_t;

```

There are 12 functions taking a `_PyTime_round_t` argument. It’s better to have 12 functions, than having 12x4 functions for each rounding mode.

* * *

The `decimal` module gets the rounding mode from the current decimal context, with the ability to pass an explicit context. Extract of `Lib/_pydecimal.py`:

```python
class Decimal(object):
    def __add__ (self, other, context=None):
        if context is None:
            context = getcontext()
        ...

```

---

<div class="post-metadata">

**Author:** ![skirpichev](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/skirpichev/32/10996_2.png) [@skirpichev](https://discuss.python.org/u/skirpichev)\
**Post date:** [June 2, 2026, 1:59am UTC](https://discuss.python.org/t/division-with-different-rounding/107587/5 "2026-06-02T01:59:30Z")

</div>

> [@vstinner](#):
>
> The `decimal` module gets the rounding mode from the current decimal context, with the ability to pass an explicit context.

Context notion is an option, which I didn’t mention. It can be used for arithmetic with builtin types, _including_ integers. That notion could customize a lot of things: rounding, behavior of true division for integer, trap floating-point errors or not, etc.

For floating-point math it was discussed [here](https://discuss.python.org/t/104388/). It’s a big change: in a lot of places (especially, optimization-related) we assume that mathematical functions (including arithmetic) are pure, while [it’s not true](https://discuss.python.org/t/contexts-for-floating-point-math/104388/21).

We can, however, consider the `context` as an alternative name for option (with a different meaning, of course). I like design of the [bigfloat](https://bigfloat.readthedocs.io/) package, which has predefined contexts with custom rounding modes, new contexts could be combined by addition like `precision(1000) + RoundTowardNegative` or explicitly constructed.

---

<div class="post-metadata">

**Author:** ![vstinner](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/vstinner/32/15130_2.png) [@vstinner](https://discuss.python.org/u/vstinner)\
**Post date:** [June 2, 2026, 9:23am UTC](https://discuss.python.org/t/division-with-different-rounding/107587/6 "2026-06-02T09:23:10Z")

</div>

> [@skirpichev](#):
>
> Context notion is an option, which I didn’t mention. It can be used for arithmetic with builtin types, _including_ integers. That notion could customize a lot of things: rounding, behavior of true division for integer, trap floating-point errors or not, etc.

The problem of context is that it can affect optimizations on integers such as the peephole bytecode optimizer, AST optimizer, JIT compiler. It would no longer be possible to compute values ahead of time if a context can change the result. So maybe it’s a bad idea.
