# Proposal: unifying division semantics

**URL:** <https://forum.modular.com/t/proposal-unifying-division-semantics/2655>\
**Category:** Mojo\
**Created:** [January 30, 2026, 2:17pm UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655 "2026-01-30T14:17:36Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![melodyogonna](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/melodyogonna/32/33_2.png) [@melodyogonna](https://forum.modular.com/u/melodyogonna)\
**Post date:** [February 2, 2026, 12:47pm UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/21 "2026-02-02T12:47:44Z")

</div>

I’m curious, what are some examples of the subtle bugs that the current behaviour can lead to?

Secondly, how would I get the current behaviour if the division return type is `Self`? Because mathematically the correct answer to 5/2 is 2.5, not 2, and I’m certain there are situations where this correctness is important.

---

<div class="post-metadata">

**Author:** ![leb-kuchen](https://avatars.discourse-cdn.com/v4/letter/l/a183cd/32.png) [@leb-kuchen](https://forum.modular.com/u/leb-kuchen)\
**Post date:** [February 2, 2026, 1:45pm UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/22 "2026-02-02T13:45:54Z")

</div>

Some ported code will be slower and some faster.  
But what about overflow or undefined division by zero or -1?

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [February 2, 2026, 4:31pm UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/23 "2026-02-02T16:31:44Z")

</div>

> [@melodyogonna](#):
>
> Secondly, how would I get the current behaviour if the division return type is `Self`? Because mathematically the correct answer to 5/2 is 2.5, not 2, and I’m certain there are situations where this correctness is important.

As long as you use `IntLiteral`, nothing changes:

```mojo
var res = 5/2 # 2.5, a float

```

This will be the new semantic for `Int` division:

```mojo
var res = Int(5)/Int(2) # 2, an Int

```

This is already the case for `SIMD` based integral types like `Int32`.

To get the current semantic back for `Int` (or any integral types):

```mojo
var a = Int(5)
var b = Int(2)
var res = Float64(a)/Float64(b) # 2.5, a float

```

---

<div class="post-metadata">

**Author:** ![JosephWakeling](https://avatars.discourse-cdn.com/v4/letter/j/c2a13f/32.png) [@JosephWakeling](https://forum.modular.com/u/JosephWakeling)\
**Post date:** [February 4, 2026, 5:02pm UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/24 "2026-02-04T17:02:41Z")

</div>

> [@christoph\_schlumpf](#):
>
> As long as you use `IntLiteral`, nothing changes:
> 
> ```auto
> var res = 5/2 # 2.5, a float
> 
> ```

Can you explain the logic of this choice in a bit more detail? It feels counter-intuitive that this one case of integer division will result in a float, but none of the others. If `T / T -> T` for any other type, why should it be different for `IntLiteral`?

---

<div class="post-metadata">

**Author:** ![nate](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/nate/32/740_2.png) [@nate](https://forum.modular.com/u/nate)\
**Post date:** [February 4, 2026, 8:19pm UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/25 "2026-02-04T20:19:17Z")

</div>

> [@christoph\_schlumpf](#):
>
> As long as you use `IntLiteral`, nothing changes:
> 
> ```auto
> var res = 5/2 # 2.5, a float
> 
> ```

I would recommend not relying on `IntLiteral` here as I could see this changing too.  
@melodyogonna - to keep the old “float” semantics, I would recommend using float literals or explicitly casting to float.  
E.g.

```mojo
var res = 5.0 / 2.0
# or
var res = Float64(5) / Float64(2)

```

---

<div class="post-metadata">

**Author:** ![Nick](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/nick/32/115_2.png) [@Nick](https://forum.modular.com/u/Nick)\
**Post date:** [February 5, 2026, 8:14am UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/26 "2026-02-05T08:14:19Z")

</div>

The proposal doc doesn’t contain enough detail to motivate the proposed change. It’s too short.

It should aim to provide a detailed answer the following question: Why do we need to diverge from Python? What problems would occur by sticking with the Python model?

Being more like C++ and Rust is not a compelling argument, because Mojo’s syntax and operators are currently completely derived from Python, and everyone expects code that looks like Python to have behaviour reminiscent of Python.

---

<div class="post-metadata">

**Author:** ![JosephWakeling](https://avatars.discourse-cdn.com/v4/letter/j/c2a13f/32.png) [@JosephWakeling](https://forum.modular.com/u/JosephWakeling)\
**Post date:** [February 5, 2026, 8:19am UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/27 "2026-02-05T08:19:03Z")

</div>

> [@leb-kuchen](#):
>
> However, removing // seems too destructive, given that a lot of Python code relies on these semantics. Thus transition would be a pain.

While non-trivial to implement, I think there may be a better long-term solution than allowing Python to constrain syntax or behaviour: implement a compile-time function that takes a string of Python code as input and translates it to equivalent mojo code.

That would make it easy for mojo to diverge where it’s useful, while allowing people to easily copy-paste from Python, and slowly migrate the resulting code.

---

<div class="post-metadata">

**Author:** ![melodyogonna](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/melodyogonna/32/33_2.png) [@melodyogonna](https://forum.modular.com/u/melodyogonna)\
**Post date:** [February 5, 2026, 9:20am UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/28 "2026-02-05T09:20:05Z")

</div>

A lot of the changes to Mojo recently makes it a bit harder to reason about than if it were its own independent language. The Python similarities are going to be very deceptive

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [February 5, 2026, 11:13am UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/29 "2026-02-05T11:13:47Z")

</div>

> [@nate](#):
>
> I would recommend not relying on `IntLiteral` here as I could see this changing too.

The proposal mentions that `IntLiteral` will not be affected and remain as is. Do you intend to change the proposal to include `IntLiteral`?

---

<div class="post-metadata">

**Author:** ![JosephWakeling](https://avatars.discourse-cdn.com/v4/letter/j/c2a13f/32.png) [@JosephWakeling](https://forum.modular.com/u/JosephWakeling)\
**Post date:** [February 5, 2026, 11:16am UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/30 "2026-02-05T11:16:14Z")

</div>

> [@melodyogonna](#):
>
> I’m curious, what are some examples of the subtle bugs that the current behaviour can lead to?

Consider the following code. Comments describe what gets printed with the current stable release of Mojo (which doesn’t yet have the proposed change):

```mojo
fn main() -> None:
    var si = SIMD[DType.int, 1](10)
    print("SIMD int: ", si / 3) # 3

    var i: Int = 10
    print("Int: ", i / 3) # 3.333333333

    var su = SIMD[DType.uint, 1](10)
    print("SIMD uint: ", su / 3) # 3

    var u: UInt = 10
    print("UInt: ", u / 3) # 3

```

So straight up we have some nasty inconsistencies in behaviour between different integer types. If I write some code that performs division, and I switch out the type of integer being used, then the behaviour of my code may change in unexpected ways. That gets worse if I’m writing, say, a generic function that accepts input of arbitrary numerical types.

> [@melodyogonna](#):
>
> Secondly, how would I get the current behaviour if the division return type is `Self`? Because mathematically the correct answer to 5/2 is 2.5, not 2, and I’m certain there are situations where this correctness is important.

That’s a good question and it will depend on you to define what “correct” means for you.

The short answer is that given integer values `a` and `b` that don’t divide evenly, you can use `Float64(a) / Float64(b)`to get Python-like behaviour. But that’s just one possibility depending on your requirements.

Consider `10/3` as a good example. Python would give you a floating-point value, 3.33333…, which is a finite approximation to the true mathematical answer. Some other programming languages (e.g. various Lisp variants) will represent this via a data structure explicitly defining a rational number, so that you don’t get hit by floating point approximation. Both have performance implications if you’re doing a lot of numerical calculations.

Either might be preferable for you as the programmer, depending on your use-case. Python is second guessing us with the assumption that most users will be satisfied with a floating-point value approximating the true mathematical result. Systems programming languages (C, C++, D, Rust, and others) will typically default to the hardware defined ops for the type (which are most performant), hence the truncate-towards-centre behaviour of integer division, and expect the programmer to specify when they want alternative (usually more expensive) behaviour, like the float conversion above.

Given that Mojo is aiming to be a systems programming language, it makes sense to follow that design principle, especially because it avoids divergence between the behaviour of built-in and SIMD integer types.

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [February 5, 2026, 11:24am UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/31 "2026-02-05T11:24:27Z")

</div>

> [@melodyogonna](#):
>
> The Python similarities are going to be very deceptive

I would state it this way: “Mojo has syntactic similarities to Python with type annotations but semantically it‘s a very different language.” At least for Phase 1 (Mojo 1.x).

---

<div class="post-metadata">

**Author:** ![melodyogonna](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/melodyogonna/32/33_2.png) [@melodyogonna](https://forum.modular.com/u/melodyogonna)\
**Post date:** [February 5, 2026, 11:50am UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/32 "2026-02-05T11:50:20Z")

</div>

> [@JosephWakeling](#):
>
> Consider the following code. Comments describe what gets printed with the current stable release of Mojo (which doesn’t yet have the proposed change):
> 
> ```auto
> fn main() -> None:
> var si = SIMD[DType.int, 1](10)
> print("SIMD int: ", si / 3) # 3
> 
> var i: Int = 10
> print("Int: ", i / 3) # 3.333333333
> 
> var su = SIMD[DType.uint, 1](10)
> print("SIMD uint: ", su / 3) # 3
> 
> var u: UInt = 10
> print("UInt: ", u / 3) # 3
> 
> ```
> 
> So straight up we have some nasty inconsistencies in behaviour between different integer types. If I write some code that performs division, and I switch out the type of integer being used, then the behaviour of my code may change in unexpected ways. That gets worse if I’m writing, say, a generic function that accepts input of arbitrary numerical types.

Seems like a problem of the language more than it is of the behaviour, but I understand now why the consistency is required.

> [@christoph\_schlumpf](#):
>
> I would state it this way: “Mojo has syntactic similarities to Python with type annotations but semantically it‘s a very different language.” At least for Phase 1 (Mojo 1.x).

There are a lot of places where the semantics are similar with just subtle differences; the mental overhead of this will add up.

---

<div class="post-metadata">

**Author:** ![JosephWakeling](https://avatars.discourse-cdn.com/v4/letter/j/c2a13f/32.png) [@JosephWakeling](https://forum.modular.com/u/JosephWakeling)\
**Post date:** [February 5, 2026, 12:47pm UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/33 "2026-02-05T12:47:53Z")

</div>

> [@BradLarson](#):
>
> As part of our ongoing efforts to unify Int with SIMD, we’ve [posted a proposal to address an inconsistency we’ve observed around integer division](https://github.com/modular/modular/blob/main/mojo/proposals/truediv.md).

I think there’s a small but significant typo in the proposal in the **Semantic Examples** section where floating point behaviour is described:

```mojo
# Float __floordiv__ follows the same semantics, but still returns Self
7.0 / 3.0 # = 2.0
7.0 // -3.0 # = -3.0 (floor toward -infinity)

```

Shouldn’t the first division example be either:

```mojo
7.0 // 3.0 # = 2.0

```

or else:

```mojo
7.0 / 3.0 # = 2.33333333333

```

… ?

---

<div class="post-metadata">

**Author:** ![owenhilyard](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/owenhilyard/32/41_2.png) [@owenhilyard](https://forum.modular.com/u/owenhilyard)\
**Post date:** [February 5, 2026, 6:29pm UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/34 "2026-02-05T18:29:33Z")

</div>

> [@Nick](#):
>
> The proposal doc doesn’t really motivate the proposed change. It’s too short.
> 
> It should aim to answer the following question in detail: Why do we need to diverge from Python? What problems would occur by sticking with the Python model?
> 
> Being more like C++ and Rust is not a compelling argument, because Mojo’s syntax and operators are currently completely derived from Python, and everyone expects code that looks like Python to have behaviour reminiscent of Python.

I think one of the main problems is that very few CPUs have the ability to do `int / int -> float` directly, and it makes the “default” kind of division very surprising to anyone coming from languages other than python. This behavior in python has been a point of surprise for many people I’ve talked to, and python somewhat hides it behind the default lack of types.

> [@JosephWakeling](#):
>
> While non-trivial to implement, I think there may be a better long-term solution than allowing Python to constrain syntax or behaviour: implement a compile-time function that takes a string of Python code as input and translates it to equivalent mojo code.
> 
> That would make it easy for mojo to diverge where it’s useful, while allowing people to easily copy-paste from Python, and slowly migrate the resulting code.

I’m not sure this is doable, given that Python can do dynamic things that Mojo cannot (ex: `exec(sys.stdin.readline())`)

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [February 6, 2026, 9:37am UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/35 "2026-02-06T09:37:02Z")

</div>

> [@melodyogonna](#):
>
> There are a lot of places where the semantics are similar with just subtle differences; the mental overhead of this will add up.

I think there are quite some important and non subtle semantical differences already, e.g.:

- Mojo value semantic vs. Python reference semantic.
- Mojo immutable default argument convention vs. Python mutable convention.
- Mojo strong compile-time typing vs. Python dynamics nature.

It might be a good idea to have a dedicated place in the documentation to highlight the difference as proposed on Discord.

---

<div class="post-metadata">

**Author:** ![JosephWakeling](https://avatars.discourse-cdn.com/v4/letter/j/c2a13f/32.png) [@JosephWakeling](https://forum.modular.com/u/JosephWakeling)\
**Post date:** [February 6, 2026, 1:46pm UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/36 "2026-02-06T13:46:48Z")

</div>

> [@owenhilyard](#):
>
> I’m not sure this is doable, given that Python can do dynamic things that Mojo cannot (ex: `exec(sys.stdin.readline())`)

Sorry, I wasn’t precise enough in explaining what I meant. It wouldn’t be about completely translating code (impossible given that language and library features don’t fully match) but about translating _syntax_. I think that should be achievable in principle.

---

<div class="post-metadata">

**Author:** ![samufi](https://avatars.discourse-cdn.com/v4/letter/s/d2c977/32.png) [@samufi](https://forum.modular.com/u/samufi)\
**Post date:** [February 8, 2026, 2:13pm UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/37 "2026-02-08T14:13:44Z")

</div>

I like Python’s behaviour that the result is aways an approximation of the mathemtaically correct result, and I find generics that lead to somewhat vastly different results based on the input type dangerous. I also see the performance arguments.

Why not constrain the `/` to floats (with a `where` clause) and enforce `//` (interpreted as int div) for integer types? Then it would always be explicit what is meant. For the mixed cased (which may be dangerous), we could use a dedicated function `flex_div` (or similar) if necessary.

I know that using the dedicated function would be “ugly”, but it would be more explicit and arguably rarely used. It would force people to think about what they want and would prevent bugs when translating Python code.

(I am aware that floor div in Python is different from int div but find this deviance acceptable.)

---

<div class="post-metadata">

**Author:** ![leb-kuchen](https://avatars.discourse-cdn.com/v4/letter/l/a183cd/32.png) [@leb-kuchen](https://forum.modular.com/u/leb-kuchen)\
**Post date:** [February 8, 2026, 4:32pm UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/38 "2026-02-08T16:32:41Z")

</div>

> [@samufi](#):
>
> Why not constrain the `/` to floats (with a where clause) and enforce `//` for integer types?

I like your idea. It’s efficient and correct by default, with only a slight ergonomic trade-off.  
Your idea is even more readable, which matters the most.  
With the property decorator, it could be made even more ergonomic. For reference, see “Unions vs. Sum Types.”

---

<div class="post-metadata">

**Author:** ![owenhilyard](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/owenhilyard/32/41_2.png) [@owenhilyard](https://forum.modular.com/u/owenhilyard)\
**Post date:** [February 8, 2026, 8:31pm UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/39 "2026-02-08T20:31:25Z")

</div>

I can see a flood of “Why doesn’t Mojo support the normal division operator?” posts.

---

<div class="post-metadata">

**Author:** ![leb-kuchen](https://avatars.discourse-cdn.com/v4/letter/l/a183cd/32.png) [@leb-kuchen](https://forum.modular.com/u/leb-kuchen)\
**Post date:** [February 9, 2026, 12:04pm UTC](https://forum.modular.com/t/proposal-unifying-division-semantics/2655/40 "2026-02-09T12:04:30Z")

</div>

> [@owenhilyard](#):
>
> Why doesn’t Mojo support the normal division operator?

It would be confusing for folks coming from a Python background.  
It’s called “ **truediv** ” for a reason, not “ **div** ,” because the latter would be mathematically incorrect.  
If Mojo proceeds with this division approach, we should at least change the dunder naming.

[Previous page](https://forum.modular.com/t/proposal-unifying-division-semantics/2655.md?page=1)

[Next page](https://forum.modular.com/t/proposal-unifying-division-semantics/2655.md?page=3)
