std::div,st...td::imaxdiv(3)

๐Ÿ“ฆ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

๐ŸŽ€ NAME ๐ŸŽ€

std::div, std::ldiv, std::lldiv, std::imaxdiv โ€” the four math girlies who do the division thing and hand you back the quotient and the remainder in one cute little struct. Welcome to the C++ Standard Library manual, section 3, and yes bestie we're doing division today ๐Ÿงฎโœจ


โœจ Synopsis โœจ

okay so here's the whole lineup, and I promise I did not lose a single one of them:

Defined in header <cstdlib>

std::div_t     div( int x, int y );                      (1)
       (constexpr since C++23)
std::ldiv_t    div( long x, long y );                    (2)
       (constexpr since C++23)
std::lldiv_t   div( long long x, long long y );          (3) (since C++11)
       (constexpr since C++23)
std::ldiv_t   ldiv( long x, long y );                    (4)
       (constexpr since C++23)
std::lldiv_t lldiv( long long x, long long y );          (5) (since C++11)
       (constexpr since C++23)

Defined in header <cinttypes>

std::imaxdiv_t div( std::intmax_t x, std::intmax_t y );  (6) (since C++11)
       (constexpr since C++23)
std::imaxdiv_t imaxdiv( std::intmax_t x, std::intmax_t y (7) (since C++11)
);
       (constexpr since C++23)

(yes, that (7) is literally sitting in that weird spot in the source, I'm not touching it, it's not my fault ๐Ÿ˜ญ)

so like, what do they actually do? they compute both the quotient and the remainder of the division of the numerator x by the denominator y. two results, one function call, we love efficiency ๐Ÿ’…

6,7) the overload of std::div for std::intmax_t is provided in <cinttypes> (since C++11) if and only if std::intmax_t is an extended integer type. that's the rule, no exceptions, periodt ๐Ÿซถ

until C++11: the quotient is the algebraic quotient with any fractional part discarded (truncated towards zero), and the remainder is such that quot * y + rem == x.

since C++11: the quotient is the result of the expression x / y, and the remainder is the result of the expression x % y. literally just the operators but wrapped in a struct, iconic behavior honestly.


๐Ÿ“ Parameters ๐Ÿ“

  • x, y โ€” integer values. that's the whole vibe check, nothing more to see here ๐Ÿ“

๐Ÿ‘‘ Return value ๐Ÿ‘‘

if both the remainder and the quotient can be represented as objects of the corresponding type (int, long, long long, std::intmax_t, respectively), it returns both as an object of type std::div_t, std::ldiv_t, std::lldiv_t, std::imaxdiv_t, defined as follows:

std::div_t

struct div_t { int quot; int rem; };

or

struct div_t { int rem; int quot; };

std::ldiv_t

struct ldiv_t { long quot; long rem; };

or

struct ldiv_t { long rem; long quot; };

std::lldiv_t

struct lldiv_t { long long quot; long long rem; };

or

struct lldiv_t { long long rem; long long quot; };

std::imaxdiv_t

struct imaxdiv_t { std::intmax_t quot; std::intmax_t rem; };

or

struct imaxdiv_t { std::intmax_t rem; std::intmax_t quot; };
โš ๏ธ and if either the remainder or the quotient cannot be represented, the behavior is undefined. like bestie do not test this, it's giving chaos ๐Ÿ˜ญ๐Ÿ’€

๐ŸŒธ Notes ๐ŸŒธ

  • until CWG issue 614 was resolved (N2757), the rounding direction of the quotient and the sign of the remainder in the built-in division and remainder operators was implementation-defined if either of the operands was negative โ€” but it was well-defined in std::div. so like, std::div was the reliable one the whole time, main character energy ๐Ÿ‘‘
  • on many platforms, a single CPU instruction obtains both the quotient and the remainder, and this function may leverage that, although compilers are generally able to merge nearby / and % where suitable. hardware said "I got you" ๐Ÿซถ

๐Ÿ’– Example ๐Ÿ’–

run this code, it's giving "I finally understand division" โœจ

// Run this code
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>

std::string division_with_remainder_string(int dividend, int divisor)
{
    auto dv = std::div(dividend, divisor);
    assert(dividend == divisor * dv.quot + dv.rem);
    assert(dv.quot == dividend / divisor);
    assert(dv.rem == dividend % divisor);

    auto sign = [](int n){ return n > 0 ? 1 : n < 0 ? -1 : 0; };
    assert((dv.rem == 0) or (sign(dv.rem) == sign(dividend)));

    return (std::ostringstream() << std::showpos << dividend << " = "
                                 << divisor << " * (" << dv.quot << ") "
                                 << std::showpos << dv.rem).str();
}

std::string itoa(int n, int radix /*[2..16]*/)
{
    std::string buf;
    std::div_t dv{}; dv.quot = n;

    do
    {
        dv = std::div(dv.quot, radix);
        buf += "0123456789abcdef"[std::abs(dv.rem)]; // string literals are arrays
    }
    while (dv.quot);

    if (n < 0)
        buf += '-';

    return {buf.rbegin(), buf.rend()};
}

int main()
{
    std::cout << division_with_remainder_string(369, 10) << '\n'
              << division_with_remainder_string(369, -10) << '\n'
              << division_with_remainder_string(-369, 10) << '\n'
              << division_with_remainder_string(-369, -10) << "\n\n";

    std::cout << itoa(12345, 10) << '\n'
              << itoa(-12345, 10) << '\n'
              << itoa(42, 2) << '\n'
              << itoa(65535, 16) << '\n';
}

Output: ๐Ÿ‘‡

+369 = +10 * (+36) +9
+369 = -10 * (-36) +9
-369 = +10 * (-36) -9
-369 = -10 * (+36) -9

12345
-12345
101010
ffff

look at those signs behaving exactly like the assertions promised, we love consistency ๐ŸŒˆ


๐Ÿฆ‹ See also ๐Ÿฆ‹

  • fmod, fmodf, fmodl (C++11) (C++11) โ€” remainder of the floating point division operation (function)
  • remainder, remainderf, remainderl (C++11) (C++11) (C++11) โ€” signed remainder of the division operation (function)
  • remquo, remquof, remquol (C++11) (C++11) (C++11) โ€” signed remainder as well as the three last bits of the division operation (function)
  • C documentation for div

(those repeated (C++11) tags are literally just the original's column layout doing its thing โ€” keeping them anyway bc rules are rules ๐Ÿ’…)


  1. Euclidean division โ€” From Wikipedia.
  2. Modulo (and Truncated division) โ€” From Wikipedia.

and that's the whole page bestie ๐Ÿซถ straight from http://cppreference.com, dated 2024.06.10, filed under std::div,st...td::imaxdiv(3) โ€” go forth and divide responsibly, and remember: quotient and remainder, together, always ๐Ÿ’œโœจ

๐Ÿ“ฆ where this page comes from