18

在 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 函数有用吗?”

4

6 回答 6

17

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

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

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

于 2011-07-16T15:10:53.177 回答
13

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;

该实现确实简单地使用了/and%运算符,因此它并不是一个非常复杂或必要的功能,但它是 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;
}
于 2011-07-16T16:07:20.763 回答
10

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

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

% 可能会返回一个否定的答案,而 div() 总是返回一个非负的余数。

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

于 2011-07-16T16:26:40.117 回答
7

div()满足了 C99 之前的需求:便携性

在 C99a / b之前,带有负操作数的商的舍入方向取决于实现。使用div()时,舍入方向不是可选的,而是指定为朝​​向 0。 div()提供了统一的可移植除法。第二用途是代码需要计算商和余数时的潜在效率。

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


这是令人信服的原因div() 它解释了 C 规范中的缺失:即使在 C99 之前,负操作数udiv_t udiv(unsigned numer, unsigned denom)的实现相关结果的问题也不存在。a/bunsigned

于 2014-09-08T22:39:23.693 回答
1

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

于 2011-07-16T15:13:09.870 回答
0

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

(原谅我英语不好,我不是本地人)

于 2011-07-16T15:12:21.120 回答