当c有/
运算符来划分两个数字时,拥有div() library function的目的是什么?
是否有任何情况/
无法使用,div()
可以?
答案 0 :(得分:13)
来自C99理由文件:
(7.20.6.2 div,ldiv和lldiv函数)因为当涉及负操作数时,C89具有用于划分有符号整数的实现定义语义,所以发明了C99中的div和ldiv以及lldiv以提供明确指定的语义有符号整数除法和余数运算的语义。采用的语义与Fortran中的语义相同。由于这些函数同时返回商和余数,因此它们也可以作为有效建模底层硬件的便捷方式 计算两个结果作为同一操作的一部分。 [...] 现在C99需要类似语义的除法运算符,这是新的主要原因 使用div,ldiv或lldiv的程序是同时获得商和余数。
答案 1 :(得分:2)
div_t
是一个结构,其中包含一个商和一个余数成员。例如:
typedef struct {
int quot;
int rem;
} div_t;
div
函数的一些简单实现使用/
和%
运算符。您还可以看到this topic。
答案 2 :(得分:2)
div()
会返回分部的result
和 remainder
。因此,您无需使用%
运算符即可找到remainder
。
答案 3 :(得分:2)
引自C Programming: A Modern Approach, 2nd Edition,第26章“问答”部分。
问:为什么div和ldiv函数存在?我们不能只使用/和%运算符吗?
A:
div
和ldiv
与/
和%
不太相同。召回 第4.1节将/
和%
应用于负操作数不会产生 便携式结果为C89。如果i
或j
为负,则是否 {<1>定义了实现,将i / j
向上或向下取整,这是<i % j
。另一方面,由div
和ldiv
计算得出的答案 不依赖于实施。商四舍五入为零。 余数根据公式n = q x d + r
计算, 其中n
是原始数字,q
是商,d
是除数,r
是余数。以下是一些示例:n | d | q | r --------|--------|--------|-------- 7 | 3 | 2 | 1 -7 | 3 | -2 | -1 7 | -3 | -2 | 1 -7 | -3 | 2 | -1
在C99中,{strong>保证
/
和%
运算符产生与以下结果相同的结果div
和ldiv
。效率是
div
和ldiv
存在的另一个原因。许多机器都有 可以同时计算商和余数的指令,因此调用div
或ldiv
可能比分别使用/
和%
运算符要更快。
答案 4 :(得分:1)
正如其他人所说,div()
会给你两个
商和其余的。这是因为(软件)整数
大多数C运行时使用的除法算法都是相同的
时间。
如果目标计算机没有硬件分隔符,则/
运营商通常会转而调用div()
和。{
其余的被扔掉了。 %
同样的事情发生了
运算符,除了它是被抛出的商。所以,如果你是
做这样的事情:
quot = a / b;
rem = a % b;
你正在调用除法程序两次(如果是,那么除法很慢)
您的计算机不在硬件中执行此操作。因此使用起来更快
div()
获得两者。
(当然,它的可读性也差,你是否真的获得了任何
性能优势取决于您的特定平台和编译器。
如果你已经确定它,你应该只切换到div()
性能瓶颈。记住Knuth所说的过早的事情
优化。)
答案 5 :(得分:0)
速度太慢,但多余。 至少 glibc doc 声明了使用 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;