在 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 函数有用吗?”
在 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
总结一下:如果您关心挤出最后一点性能,这可能是您选择的功能,特别是如果您平台上的优化器不是那么先进。这通常是嵌入式平台的情况。否则,请使用您认为更具可读性的任何方式。
div() 函数返回一个结构,其中包含第一个参数(分子)除以第二个参数(分母)的商和余数。有四种变体:
div_t div(int, int)
ldiv_t ldiv(long, long)
lldiv_t lldiv(long long, long long)
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;
}
div() 的语义不同于 % 和 / 的语义,这在某些情况下很重要。这就是为什么以下代码在 psYchotic 的答案中显示的实现中:
if (numer >= 0 && result.rem < 0)
{
++result.quot;
result.rem -= denom;
}
% 可能会返回一个否定的答案,而 div() 总是返回一个非负的余数。
检查WikiPedia 条目,特别是“div 总是向 0 舍入,这与 C 中的普通整数除法不同,其中负数的舍入取决于实现。”
div()
满足了 C99 之前的需求:便携性
在 C99a / b
之前,带有负操作数的商的舍入方向取决于实现。使用div()
时,舍入方向不是可选的,而是指定为朝向 0。 div()
提供了统一的可移植除法。第二个用途是代码需要计算商和余数时的潜在效率。
使用 C99 及更高版本,div()
并/
指定相同的圆形方向以及更好的编译器优化附近a/b
和a%b
代码,需求已经减少。
这是令人信服的原因div()
,它解释了 C 规范中的缺失:即使在 C99 之前,负操作数udiv_t udiv(unsigned numer, unsigned denom)
的实现相关结果的问题也不存在。a/b
unsigned
可能是因为在许多处理器上 div 指令会同时生成这两个值,并且您始终可以依靠编译器来识别相同输入上的相邻 / 和 % 运算符可以合并为一个操作。
如果您需要两种价值,则花费更少的时间。CPU 在执行除法时总是计算余数和商。如果使用一次“/”和一次“%”,cpu 将计算两次。
(原谅我英语不好,我不是本地人)