div函数有用吗(stdlib.h)?

在C,C ++中有一个名为div的函数(stdlib.h)

div_t div(int numer, int denom); typedef struct _div_t { int quot; int rem; } div_t; 

但C,C ++有/和%运算符。

我的问题是:“ 当有/和%运算符时,div函数有用吗?”

div()函数返回一个结构,该结构包含第一个参数(分子)除以第二个(分母)的除数和余数。 有四种变体:

  1. div_t div(int, int)
  2. ldiv_t ldiv(long, long)
  3. lldiv_t lldiv(long long, long long)
  4. imaxdiv_t imaxdiv(intmax_t, intmax_t (intmax_t表示系统上可用的最大整数类型)

div_t结构如下所示:

 typedef struct { int quot; /* Quotient. */ int rem; /* Remainder. */ } div_t; 

实现只是使用/%运算符,因此它不是一个非常复杂或必要的函数,但它是C标准的一部分(由[ISO 9899:201x] [1]定义)。

请参阅GNU libc中的实现:

 /* Return the `div_t' representation of NUMER over DENOM. */ div_t div (numer, denom) int numer, denom; { div_t result; result.quot = numer / denom; result.rem = numer % denom; /* The ANSI standard says that |QUOT| <= |NUMER / DENOM|, where NUMER / DENOM is to be computed in infinite precision. In other words, we should always truncate the quotient towards zero, never -infinity. Machine division and remainer may work either way when one or both of NUMER or DENOM is negative. If only one is negative and QUOT has been truncated towards -infinity, REM will have the same sign as DENOM and the opposite sign of NUMER; if both are negative and QUOT has been truncated towards -infinity, REM will be positive (will have the opposite sign of NUMER). These are considered `wrong'. If both are NUM and DENOM are positive, RESULT will always be positive. This all boils down to: if NUMER >= 0, but REM < 0, we got the wrong answer. In that case, to get the right answer, add 1 to QUOT and subtract DENOM from REM. */ if (numer >= 0 && result.rem < 0) { ++result.quot; result.rem -= denom; } return result; } 

是的,它是:它在一次操作中计算商和余数。

除此之外,使用/ + %可以实现相同的行为(并且一个体面的优化器无论如何都会将它们优化为单个div )。

总结一下:如果你关心挤出最后一点性能,这可能是你选择的function,特别是如果平台上的优化器不是那么先进。 嵌入式平台通常就是这种情况。 否则,请使用您认为更具可读性的任何方式。

div()的语义不同于%和/的语义,这在某些情况下很重要。 这就是为什么以下代码在psYchotic的答案中显示的实现:

 if (numer >= 0 && result.rem < 0) { ++result.quot; result.rem -= denom; } 

%可能会返回否定答案,而div()始终返回非负余数。

检查WikiPedia条目 ,特别是“div总是向0舍入,与C中的普通整数除法不同,其中负数的舍入取决于实现。”

div()满足了C99之前的需求:可移植性

在C99之前 ,带有负操作数的a / b商的舍入方向取决于实现。 使用div() ,舍入方向不是可选的,而是指定为0. div()提供统一的便携式除法。 次要用途是在计算商和余数时所需的代码的潜在效率。

使用C99及更高版本, div()/指定相同的圆形方向,并且使用更好的编译器优化附近的a/ba%b代码,需求减少了。


这是div()的令人信服的理由它解释了在C规范中缺少udiv_t udiv(unsigned numer, unsigned denom) :带有负操作数的a/b的实现依赖结果的问题对于unsigned是不存在的,即使在预C99。

如果您需要两个值,则花费的时间更少。 执行除法时,CPU始终计算余数和商。 如果使用“/”一次和“%”一次,cpu将计算两次数。

(原谅我可怜的英语,我不是本地人)

可能是因为在许多处理器上,div指令产生两个值,并且您始终可以依赖编译器来识别相同输入上的相邻/和%运算符可以合并为一个操作。