8

当 C 有/运算符将两个数字相除时,具有div()库函数的目的是什么?

/有没有不能用但能用的场景div()

4

6 回答 6

18

来自 C99 基本原理文档:

(7.20.6.2 div、ldiv 和 lldiv 函数)因为 C89 在涉及负操作数时具有实现定义的有符号整数除法语义,所以发明了 div 和 ldiv 以及 C99 中的 lldiv,以便为有符号整数提供明确指定的语义整数除法和余数运算。语义被采用与 Fortran 中的相同。由于这些函数同时返回商和余数,因此它们还可以作为一种有效建模底层硬件的便捷方法,将计算这两个结果作为同一操作的一部分。[...] 现在 C99 要求除法运算符具有类似的语义,新程序使用 div、ldiv 或 lldiv 的主要原因是同时获得商和余数。

于 2012-07-30T16:51:42.907 回答
3

引自C 编程:现代方法,第 2 版,第 26 章,问答部分。

问:为什么存在 div 和 ldiv 函数?我们不能只使用 / 和 % 运算符吗?

A:divand 和 and不太ldiv一样。回想一下第 4.1 节,在 C89 中将和应用于负操作数不会给出可 移植的结果。如果or是负数, 的值 是向上还是向下舍入是实现定义的,就像 的符号一样 。另一方面, 由and计算的答案不依赖于 implementation。商向零舍入;余数根据公式计算,其中是原数,是商,是除数,/%/%iji / ji % jdivldivn = q x d + rnqdr是余数。这里有一些例子:

 n      |  d     |  q     |  r
--------|--------|--------|--------
 7      |  3     |  2     |  1
-7      |  3     | -2     | -1
 7      | -3     | -2     |  1
-7      | -3     |  2     | -1

在 C99 中,/and%运算符保证div产生与and相同的结果 ldiv

效率是存在的另一个div原因ldiv。许多机器都有一个可以计算商和余数的指令,因此调用div orldiv可能比单独使用and运算符更快/%

于 2018-11-10T03:09:00.663 回答
2

div_t是一个结构,它包含一个商成员一个余数成员。例如 :

typedef struct {
    int quot;
    int rem;
} div_t;

div函数使用/和操作符的一些简单实现%。你也可以看到这个话题

于 2012-07-30T16:45:42.730 回答
2

div()返回result除法的remainder。因此,您不必使用%运算符来查找remainder.

于 2012-07-30T16:47:45.667 回答
1

正如其他人所提到的,div()会给你商和余数。这是因为大多数 C 运行时使用的(软件)整数除法算法同时计算两者。

如果目标计算机没有硬件分隔器,则/ 操作员通常会被调用,div()而其余的则被丢弃。运算符也会发生同样的事情,% 只是它是被抛出的商。所以如果你正在做这样的事情:

quot = a / b;
rem = a % b;

您调用了两次除法例程(如果您的计算机不在硬件中执行,除法会非常慢)。所以使用 div()两者都更快。

(当然,它的可读性也较差,您是否真正获得任何性能优势取决于您的特定平台和编译器。只有div()在确定它是性能瓶颈时才应该切换到它。记住 Knuth 所说的过早优化。)

于 2012-07-30T17:13:09.293 回答
0

太慢了,却又是多余的。 至少 glibc 文档说明了使用 gcc 的情况。我尝试 div 重新实现现有的 itoa() 函数(整数到 ascii),期望 gcc 有内置实现这样一个微不足道的事情,但 gcc 没有它。

char *p = buf;
div_t d = {.quot = n};

while (1)
    d = div (d.quot, 10) ,
    *p++ = '0' + d.rem   ;

上面的代码比使用单独的运算符慢 5..7 倍:

char *p = buf;

while (1)
    *p++ = '0' + n % 10,
    n /= 10;
于 2021-08-02T17:00:07.177 回答