---
title: "The name of the floor division function should have floor in it"
document: P4259R0
date: 2026-07-15
audience: LEWG
reply-to:
  - "Barry Revzin <barry.revzin@gmail.com>"
---

No syntax highlighting

Hide deleted text

# Introduction

In 1962, Kenneth Iverson introduced the names “floor” and “ceiling”, and the syntax `⌊x⌋` and `⌈x⌉`, for operations that return the greatest integer less than or equal to `x` and the smallest integer greater than or equal to `x`, respectively. Since then, these names have become broadly used in math and programming.

Here is a list of programming languages and the name they give their functions for these operations:

| Language | Greatest integer ≤ x | Smallest integer ≥ x |
| --- | --- | --- |
| C | `floor` | `ceil` |
| C++ | `std::floor` | `std::ceil` |
| C# | `Math.Floor` | `Math.Ceiling` |
| Java | `Math.floor` | `Math.ceil` |
| Kotlin | `floor` | `ceil` |
| Swift | `floor` | `ceil` |
| Rust | `f64::floor` | `f64::ceil` |
| Go | `math.Floor` | `math.Ceil` |
| Python | `math.floor` | `math.ceil` |
| JavaScript | `Math.floor` | `Math.ceil` |
| TypeScript | `Math.floor` | `Math.ceil` |
| Ruby | `floor` | `ceil` |
| PHP | `floor` | `ceil` |
| R | `floor` | `ceiling` |
| Julia | `floor` | `ceil` |
| Haskell | `floor` | `ceiling` |
| OCaml | `floor` | `ceil` |
| F# | `floor` | `ceil` |
| Elixir | `Float.floor` | `Float.ceil` |
| Erlang | `math:floor` | `math:ceil` |
| Lua | `math.floor` | `math.ceil` |
| MATLAB | `floor` | `ceil` |
| Octave | `floor` | `ceil` |
| Fortran | `floor` | `ceiling` |
| Clojure | `math/floor` | `math/ceil` |
| Excel<sup>1</sup> | `FLOOR` | `CEILING` |

There simply is not a lot of diversity in the names of these functions. But that’s for unary floating point/decimal operations. Many languages also offer binary integer functions that return the mathematical results of `⌊x/y⌋` and `⌈x/y⌉`. There is a bit more diversity to those operations:

| Language | `⌊x/y⌋` | `⌈x/y⌉` |
| --- | --- | --- |
| Rust<sup>2</sup> | `x.div_floor(y)` | `x.div_ceil(y)` |
| Zig | `@divFloor(x, y)` | `@divCeil(x, y)` |
| MATLAB | `idivide(x, y, "floor")` | `idivide(x, y, "ceil")` |
| Racket<sup>3</sup> | `(floor-quotient x y)` | `(ceiling-quotient x y)` |
| Clojure | `(floor-div x y)` | n/a |
| Java | `Math.floorDiv(x, y)` | `Math.ceilDiv(x, y)` |
| Common LISP | `(floor x y)` | `(ceiling x y)` |
| Nim | `floorDiv(x, y)` | `ceilDiv(x, y)` |
| Ruby | `x.div(y)` or `x/y` | `x.ceildiv(y)` |
| Scala | `Math.floorDiv(x, y)` | `Math.ceilDiv(x, y)` |
| Elixir | `Integer.floor_div(x, y)` | `Integer.ceil_div(x, y)` |
| Julia | `div(x, y, RoundDown)` or `fld(x, y)` | `div(x, y, RoundUp)` or `cld(x, y)` |
| Swift | `x.divided(by: y, rounding: .down)` | `x.divided(by: y, rounding: .up)` |

Not all languages provide integer division functions of this form — some simply rely on their regular integer division operation for doing floor division (since in C++, `-5 / 2` is `-2` but in some languages it is `-3`). Nevertheless, there is still a great deal of uniformity in the API space here.

There are only two languages I’ve found which provide both operations and also do not use the word floor or ceiling in them, which I deliberately put last in the above table: both [Julia](https://docs.julialang.org/en/v1/base/math/#Base.div-Tuple%7BAny,%20Any,%20RoundingMode%7D) and [Swift Numerics](https://github.com/apple/swift-numerics/blob/main/Sources/IntegerUtilities/README.md) provide integer division as ternary functions that take a rounding mode, and in both cases the rounding mode for floor is spelled “down” while the rounding mode for ceiling is spelled “up.” Nevertheless, Julia still provides a terser form that is simply `fld` and `cld`. Which makes Swift unique in this regard.

## The C++29 Proposal

Meanwhile, [[P3724R4] (Integer division)](https://wg21.link/p3724r4) introduces a number of integer division functions with different rounding modes (10 rounding modes and Euclidean division). That proposal’s names for the two rounding modes described above are:

| Language | `⌊x/y⌋` | `⌈x/y⌉` |
| --- | --- | --- |
| P3724 | `std::div_to_neg_inf(x, y)` | `std::div_to_pos_inf(x, y)` |

That is extremely different from established practice. It doesn’t match any existing programming language that I’ve found, including the names of the rounding modes in IEEE 754 (`roundTowardNegative` and `roundTowardPositive`, respectively) or the `fesetround` constants (`FE_DOWNWARD` and `FE_UPWARD`, respectively). It does almost match the existing `std::float_round_style::round_toward_neg_infinity`, but this is a rounding mode, not the name of a function or operation.

The proposal’s justification for these names is:

While the use of names like floor and ceil is common in various domains, including in `<cmath>`, I do not believe we should perpetuate this design for integer division.

Anecdotally, during the LEWG telecon for P3724R3, there was visible confusion when the room was asked

> What does `div_floor` do for negative numbers?

While the answer may be obvious to a mathematician, that does not apply to everyone. The key benefit of the proposed naming scheme is that it is entirely self-documenting.

To provide some more rationale:

- The proposed scheme does not nicely extend to division with rounding away from zero; there is no established term for that.
- A hypothetical `std::div_round` (for rounding to the nearest integer) would be somewhat perplexing because all proposed functions round, just toward different targets. However, taking `std::div_floor` as a counterpart to `std::floor` strongly suggests that there should be a `std::div_round` function as a counterpart to `std::round`, which is not the case.

Regardless whether the functions end up called `std::div_floor` or `std::div_to_neg_inf`, the names should remain somewhat brief so they take up a reasonable amount of space in C++ expressions.

## A Response to the Rationale

Indeed, the use of names like floor and ceil is common. Not just common, but all but ubiquitous, to the point where people will naturally look for these functions under those names. As in: “What is C++’s integer floor division function?”

The answer to what `div_floor` does for negative numbers is of course the same as it is for positive numbers: it gives the largest integer less than or equal to the quotient. It is difficult to accept the claim that this is hard for a non-mathematician to understand, while `div_to_neg_inf` is somehow easier, especially given the landscape that we find ourselves in. Additionally, `to_neg_inf` is appreciably more mathematically-oriented than `floor` (not to mention `down`).

That there is no established term for rounding away from zero (the only languages I’m aware of that provide this mode only provide it in the ternary form where the rounding mode is an operand) does not mean that we should ignore the fact that there *is* an established term for floor and ceiling division. And even for rounding away from zero, the paper’s choice of naming is too terse. Both Swift and Julia call this rounding *from* zero, whereas the proposed name is just “away zero”:

| Language | Integer Division, rounding away from zero |
| --- | --- |
| Julia | `div(x, y, RoundFromZero)` |
| Swift | `x.divided(by: y, rounding: .awayFromZero)` |
| Proposed C++ | `std::div_away_zero(x, y)` |

I also don’t find a hypothetical `div_round` all that perplexing either. Arguably that’s the very clear analogue to the floating point function we already have, which makes it easily discoverable. After all, we have these four unary floating point operations, and the integer division functions conceptually do the same thing as a floating point division followed by the particular specified rounding (of course without actually round-tripping through floating point types and entirely avoiding any potential rounding errors):

| Unary Floating Point | Binary Integer Division |
| --- | --- |
| `floor` | `div_floor` |
| `ceil` | `div_ceil` |
| `round` | `div_round` |
| `trunc` | `div_trunc` |

Although the last of these, `div_trunc(x, y)` — which in the paper is proposed as `div_to_zero(x, y)` — is probably the least interesting and unlikely to be used, since it is simply `x / y`.

## The Other Rounding Modes

For the less ubiquitous rounding modes, the names should prioritize clarity over minimizing the number of characters. To compare the names of the other functions proposed in [[P3724R4]](https://wg21.link/p3724r4) to the rounding modes provided in Julia and Swift, I think the proposed names are the worst of the three:

| Julia | Swift | P3724 |
| --- | --- | --- |
| `div(x, y, RoundNearestTiesAway)` | `x.divided(by: y, rounding: .toNearestOrAway)` | `div_ties_away_zero(x, y)` |
| `div(x, y, RoundNearestTiesUp)` | `x.divided(by: y, rounding: .toNearestOrUp)` | `div_ties_to_pos_inf(x, y)` |
| `div(x, y, RoundToZero)` | `x.divided(by: y, rounding: .towardZero)` | `div_to_zero(x, y)` |
| `div(x, y, RoundFromZero)` | `x.divided(by: y, rounding: .awayFromZero)` | `div_away_zero(x, y)` |

There’s probably a good argument that the common rounding modes (floor, ceiling) and Euclidean division merit their own named functions, while the rest can be handled via a rounding mode enumeration as in Julia ([7 options](https://docs.julialang.org/en/v1/base/math/#Base.Rounding.RoundingMode)), Swift ([11 options](https://github.com/apple/swift-numerics/blob/main/Sources/IntegerUtilities/RoundingRule.swift)), and Matlab ([4 options](https://www.mathworks.com/help/matlab/ref/idivide.html)).

The paper’s argument *against* such a rounding mode function argument is:

In virtually every case, the rounding mode for an integer division is a fixed choice. This is evidenced by the ten trillion existing uses of the / operator which always truncate. Also, the implementation of the proposed functions does not lend itself to a runtime parameter:

[…]

As can be seen, these implementations are substantially different.

[…]

If we now provided a runtime `std::rounding`, the obvious implementation would look like:

> ```cpp
> enum struct rounding { to_zero, to_neg_inf, away_zero, /* ... */ };
> 
> int divide(int x, int y, rounding_mode mode) {
>   switch (mode) {
>   case rounding::to_zero:    return __div_to_zero(x);
>   case rounding::to_neg_inf: return __div_to_neg_inf(x);
>   case rounding::away_zero:  return __div_away_zero(x);
>   // ...
>   }
>   std::unreachable();
> }
> ```

The user can trivially make such an enum class and switch themselves, if they actually need to. If they don’t (which is likely), all we accomplish is making the user write `std::divide(std::rounding::to_neg_inf, x, y)` instead of `std::div_to_neg_inf(x, y)`.

To start with, there are many claims here that I think are just obviously true: that the rounding mode is almost always a fixed choice, that the implementations of the different modes are substantively different, and that the likely implementation will be the `switch` presented here. But I don’t actually think this is an argument against such a shape.

What we’re actually doing here is parametrizing an algorithm — a rounding mode parameter allows us to clearly separate the algorithm (division) from the parameter (the rounding mode). Even if all of the different rounding mode approaches are consistently named as `div_`, having them have literally the same name is still an improvement.

Since the rounding mode will almost always be passed in as a constant, that `switch` implementation will [reliably optimize out](https://compiler-explorer.com/z/1xEdj9Gs3) (the two linked implementations have identical codegen even with `-Og`). And in the rare situations where the rounding mode is non-constant, having it be a parameter allows that use-case at all.

And the spelling of the mode allows for more straightforwardly readable spellings of the rarer rounding modes, which is I think a good win. Let’s go through a few rounding modes, using Swift’s naming approach.

Toward zero:

> ```cpp
> x / y                                  // just the language operator
> div_trunc(x, y)                        // following trunc()
> div_to_zero(x, y)                      // P3724
> div(x, y, rounding::toward_zero)       // with mode
> ```

Away from zero:

> ```cpp
> div_away_zero(x, y)                    // P3724
> div(x, y, rounding::away_from_zero)    // with mode
> ```

To the nearest integer, rounding ties up:

> ```cpp
> div_ties_to_pos_inf(x, y)                // P3724
> div(x, y, rounding::to_nearest_or_ceil)  // with mode
> ```

Of course, the ones that explicitly provide a rounding mode are longer than the other options — although the relative margin of difference goes down if the variable names are longer than a single character. But the enum allows for, and arguably even forces, clearer names.

I think clearer names are more valuable than terser names for these functions — especially for these more rarely used rounding modes.

## Floor and Ceiling as Rounding Modes

If we have an enumeration for the rounding modes, what should we call the rounding mode equivalents of the operations `div_floor` and `div_ceil`?

I’ve been arguing that the *operations* should be named `floor` and `ceil`, since that’s what people will search for. Floor and ceiling are the names of those operations. But they aren’t necessarily rounding *modes* — rounding mode is more like “toward zero” or “up.” This is the same naming distinction that Julia makes: `fld` and `cld` for the operations but `RoundDown` and `RoundUp` for the rounding mode. It’s this question of mode that explains why there shouldn’t be an enumerator for `rounding::euclid` — that’s not a rounding mode, that’s a different algorithm.

I think the three pairs that make sense are:

- `ceil` and `floor` (after the operations)
- `up` and `down` (e.g. Swift, Julia, `fesetround`)
- `toward_positive` and `toward_negative` (e.g. IEEE)

Now, it turns out that the names `up` and `down` have some interesting usage. In Swift and Julia, they mean moving the number up and down the number line — `1.5` rounds up to `2` and `-1.5` rounds up to `-1`. But Java’s [`RoundingMode`](https://docs.oracle.com/javase/8/docs/api/java/math/RoundingMode.html), Python’s [`decimal`](https://docs.python.org/3/library/decimal.html#rounding-modes), and Ruby’s [`BigDecimal`](https://rubydoc.info/gems/bigdecimal/BigDecimal) all provide *both* `UP` and `DOWN` *and* `CEILING` and `FLOOR`. Not as synonyms — these are four distinct rounding modes. All of these come from IBM’s [General Decimal Arithmetic specification](https://speleotrove.com/decimal/decarith.pdf), which defines these rounding modes:

| mode name | definition |
| --- | --- |
| round-down | (Round toward 0; truncate.) The discarded digits are ignored; the result is unchanged. |
| round-half-up | … |
| round-half-even | … |
| round-ceiling | (Round toward +∞.) If all of the discarded digits are zero or if the sign is 1 the result is unchanged. Otherwise, the result coefficient should be incremented by 1 (rounded up). |
| round-floor | (Round toward -∞.) If all of the discarded digits are zero or if the sign is 0 the result is unchanged. Otherwise, the sign is 1 and the result coefficient should be incremented by 1. |
| round-half-down | … |
| round-up | (Round away from 0.) If all of the discarded digits are zero the result is unchanged. Otherwise, the result coefficient should be incremented by 1 (rounded up). |
| round-05up | … |

Personally, I think “toward zero” is a perfectly good way to express rounding toward zero, which has the benefit that I can continue to view it as a number line rather than a number parabola in which “down” means two different directions. But the divergence in existing practice of what rounding “up” and “down” means, especially given that multiple languages actually provide UP and CEILING as distinct modes, suggests that we should not simply copy the Julia and Swift naming approach.

Given that, and given that the decimal-arithmetic languages demonstrate floor and ceiling being used as rounding *mode* names — even though I earlier characterized them as *operation* names — I see no reason not to use `floor` and `ceil` for the modes too.

# Proposal

The names `std::div_to_pos_inf` and `std::div_to_neg_inf` proposed by [[P3724R4]](https://wg21.link/p3724r4) are poor names. There is broadly established precedent for referring to these operations as ceiling and floor division, respectively. People looking for these operations will look for them *under those names*. The names should reflect that.

For the less common rounding modes, I think we should seriously consider simply passing the rounding mode as a function argument. Having a rounding mode enumeration doesn’t preclude explicit names for the more common operations, and there’s existing practice for just that in Julia. At the very least, the names of several of the rounding modes should be reconsidered to read better. The proposed `div_away_zero` is the worst of the names since it’s just missing a preposition, but the family of nearest rounding rules aren’t very well named either since they omit the “nearest” part in the name — you just have to know that `div_ties_to_even` has an implicit `to_nearest` in the name (e.g. Swift names this mode `toNearestOrEven`).

Concretely, something like:

> ```cpp
> template<class T> constexpr T div_floor(T x, T y);
> template<class T> constexpr T div_ceil(T x, T y);
> template<class T> constexpr T div_euclid(T x, T y); // as in P3724
> 
> template<class T> constexpr T rem_euclid(T x, T y); // as in P3724
> 
> template<class T> constexpr div_result<T> div_rem_floor(T x, T y);
> template<class T> constexpr div_result<T> div_rem_ceil(T x, T y);
> template<class T> constexpr div_result<T> div_rem_euclid(T x, T y); // as in P3724
> 
> enum class rounding {
>     // directed rules
>     floor,
>     ceil,
>     toward_zero,
>     away_from_zero,
> 
>     // nearest rules
>     to_nearest_or_floor,
>     to_nearest_or_ceil,
>     to_nearest_or_zero,
>     to_nearest_or_away,
>     to_nearest_or_even,
>     to_nearest_or_odd,
> };
> 
> template<class T> constexpr T div(T x, T y, rounding mode);
> template<class T> constexpr div_result<T> div_rem(T x, T y, rounding mode);
> ```

Note that `std::div` already exists — and returns not just the quotient but both the quotient and remainder together (as proposed in the better named `div_rem` family). I think this is okay because `std::div` in its current form isn’t very useful, due to two flaws:

1. It isn’t inlined in either libstdc++ or libc++, so even something as trivial as `std::div(x, 2)` [doesn’t optimize at all](https://compiler-explorer.com/z/6fa1a8WYP).
2. It returns a struct whose member order isn’t actually specified, so while `auto [quot, rem] = std::div(x, y);` compiles, you have no guarantees as to whether `quot` is the quotient or the remainder.

Additionally, I think we’re already okay with the existing proposal naming its family of functions `div_*` that only return the quotient even though the existing `std::div` returns both.

# References

[P3724R4] Jan Schultke. 2026-05-10. Integer division.

https://wg21.link/p3724r4

---

1. Excel’s `FLOOR` and `CEILING` are actually binary: they take a significance argument.↩︎
2. Rust’s `div_ceil` is stable for unsigned integers but unstable for signed integers; `div_floor` is unstable for both (since unsigned floor division is just `/`).↩︎
3. Not in Core Racket, but rather in [SRFI 141](https://srfi.schemers.org/srfi-141/srfi-141.html). Note that this also has Euclidean division, as well as truncating, rounding to nearest (ties to even), and balanced.↩︎
