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

发布于 2024-11-24 13:40:00 字数 240 浏览 0 评论 0原文

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

div_t div(int numer, int denom);

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

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

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

There is a function called div in C,C++ (stdlib.h)

div_t div(int numer, int denom);

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

But C,C++ have / and % operators.

My question is: "When there are / and % operators, Is div function useful?"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

轮廓§ 2024-12-01 13:40:00

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

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

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

Yes, it is: it calculates the quotient and remainder in one operation.

Aside from that, the same behaviour can be achieved with /+% (and a decent optimizer will optimize them into a single div anyway).

In order to sum it up: if you care about squeezing out last bits of performance, this may be your function of choice, especially if the optimizer on your platform is not so advanced. This is often the case for embedded platforms. Otherwise, use whatever way you find more readable.

遥远的她 2024-12-01 13:40:00

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

  1. div_t div(int, int)
  2. ldiv_t ldiv(long, long)
  3. lldiv_t lldiv(long long, long long)
  4. < code>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;
}

The div() function returns a structure which contains the quotient and remainder of the division of the first parameter (the numerator) by the second (the denominator). There are four variants:

  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 represents the biggest integer type available on the system)

The div_t structure looks like this:

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

The implementation does simply use the / and % operators, so it's not exactly a very complicated or necessary function, but it is part of the C standard (as defined by [ISO 9899:201x][1]).

See the implementation in 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;
}
套路撩心 2024-12-01 13:40:00

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

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

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

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

The semantics of div() is different than the semantics of % and /, which is important in some cases.
That is why the following code is in the implementation shown in psYchotic's answer:

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

% may return a negative answer, whereas div() always returns a non-negative remainder.

Check the WikiPedia entry, particularly "div always rounds towards 0, unlike ordinary integer division in C, where rounding for negative numbers is implementation-dependent."

转角预定愛 2024-12-01 13:40:00

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

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

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


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

div() filled a pre-C99 need: portability

Pre C99, the rounding direction of the quotient of a / b with a negative operand was implementation dependent. With div(), the rounding direction is not optional but specified to be toward 0. div() provided uniform portable division. A secondary use was the potential efficiency when code needed to calculate both the quotient and remainder.

With C99 and later, div() and / specifying the same round direction and with better compilers optimizing nearby a/b and a%b code, the need has diminished.


This was the compelling reason for div() and it explains the absence of udiv_t udiv(unsigned numer, unsigned denom) in the C spec: The issues of implementation dependent results of a/b with negative operands are non-existent for unsigned even in pre-C99.

稀香 2024-12-01 13:40:00

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

Probably because on many processors the div instruction produces both values and you can always count on the compiler to recognize that adjacent / and % operators on the same inputs could be coalesced into one operation.

百思不得你姐 2024-12-01 13:40:00

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

(原谅我的英语不好,我不是母语)

It costs less time if you need both value.
CPU always calculate both remainder and quotient when performing division.
If use "/" once and "%" once, cpu will calculate twice both number.

(forgive my poor English, I'm not native)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文