div, ldiv, lldiv, imaxdiv

< c‎ | numeric‎ | math
在标头 <stdlib.h> 定义
div_t     div( int x, int y );
(1)
ldiv_t    ldiv( long x, long y );
(2)
lldiv_t   lldiv( long long x, long long y );
(3) (C99 起)
在标头 <inttypes.h> 定义
imaxdiv_t imaxdiv( intmax_t x, intmax_t y );
(4) (C99 起)

计算分子 x 除以分母 y 的商和余数。

同时计算商和余数。商为舍弃小数部分(向零取整)的代数商。余数满足 quot * y + rem == x

(C99 前)

同时计算商(表达式 x / y 的结果)和余数(表达式 x % y 的结果)。

(C99 起)

参数

x, y - 整数值

返回值

若余数和商都能表示成对应类型的对象(分别为 intlonglong longintmax_t),则将两者作为返回作为定义如下的 div_tldiv_tlldiv_timaxdiv_t 类型对象返回:

div_t

struct div_t { int quot; int rem; };

struct div_t { int rem; int quot; };

ldiv_t

struct ldiv_t { long quot; long rem; };

struct ldiv_t { long rem; long quot; };

lldiv_t

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

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

imaxdiv_t

struct imaxdiv_t { intmax_t quot; intmax_t rem; };

struct imaxdiv_t { intmax_t rem; intmax_t quot; };

若余数或商无法表示,则行为未定义。

注意

C99 前,若操作数之一为负,则内建的除法和取余运算符中的商取整方向和余数符号是实现定义的,但它在 divldiv 中良好定义。

多数平台上,单条 CPU 指令可同时获得商和余数,而此函数可以活用这点,尽管编译器通常能在适合处合并临近的 / 和 %。

示例

#include <assert.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
 
void reverse(char* first, char* last)
{
    for (--last; first < last; ++first, --last)
    {
        char c = *last;
        *last = *first;
        *first = c;
    }
}
 
// 缓冲区溢出的情况下返回空缓冲区
char* itoa(int n, int base, char* buf, size_t buf_size)
{
    assert(2 <= base && base <= 16 && buf && buf_size);
    div_t dv = {.quot = n};
    char* p = buf;
    do
    {
        if (!--buf_size)
            return (*buf = '\0'), buf;
        dv = div(dv.quot, base);
        *p++ = "0123456789abcdef"[abs(dv.rem)];
    }
    while(dv.quot);
    if (n < 0)
        *p++ = '-';
    *p = '\0';
    reverse(buf, p);
    return buf;
}
 
int main(void)
{
    char buf[16];
    printf("%s\n", itoa(0, 2, buf, sizeof buf));
    printf("%s\n", itoa(007, 3, buf, sizeof buf));
    printf("%s\n", itoa(12346, 10, buf, sizeof buf));
    printf("%s\n", itoa(-12346, 10, buf, sizeof buf));
    printf("%s\n", itoa(-42, 2, buf, sizeof buf));
    printf("%s\n", itoa(INT_MAX, 16, buf, sizeof buf));
    printf("%s\n", itoa(INT_MIN, 16, buf, sizeof buf));
}

可能的输出:

0
21
12346
-12346
-101010
7fffffff
-80000000

引用

  • C23 标准(ISO/IEC 9899:2024):
  • 7.8.2.2 The imaxdiv function (第 TBD 页)
  • 7.22.6.2 The div, ldiv and lldiv functions (第 TBD 页)
  • C17 标准(ISO/IEC 9899:2018):
  • 7.8.2.2 The imaxdiv function (第 159 页)
  • 7.22.6.2 The div, ldiv and lldiv functions (第 259 页)
  • C11 标准(ISO/IEC 9899:2011):
  • 7.8.2.2 The imaxdiv function (第 219 页)
  • 7.22.6.2 The div, ldiv and lldiv functions (第 356 页)
  • C99 标准(ISO/IEC 9899:1999):
  • 7.8.2.2 The imaxdiv function (第 200 页)
  • 7.20.6.2 The div, ldiv and lldiv functions (第 320 页)
  • C89/C90 标准(ISO/IEC 9899:1990):
  • 4.10 div_t, ldiv_t
  • 4.10.6.2 The div function
  • 4.10.6.4 The ldiv function

参阅

(C99)(C99)
计算浮点除法运算的余数
(函数)
计算浮点除法运算的带符号余数
(函数)
(C99)(C99)(C99)
计算除法运算的带符号余数,以及商的后三位
(函数)

外部链接

1.  欧几里得除法 — 来自 Wikipedia
2.  取模(和截断除法) — 来自 Wikipedia