在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函数是否有用?”
答案 0 :(得分:16)
是的,它是:它计算一个操作中的商和余数。
除此之外,使用/
+ %
可以实现相同的行为(并且一个不错的优化器会将它们优化为单个div
。)
为了总结一下:如果你关心挤出最后一点性能,这可能是你选择的功能,特别是如果平台上的优化器不是那么先进的话。嵌入式平台通常就是这种情况。否则,请使用您认为更具可读性的任何方式。
答案 1 :(得分:13)
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;
实现只使用/
和%
运算符,因此它不是一个非常复杂或必要的函数,但它是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;
}
答案 2 :(得分:9)
div()的语义不同于%和/的语义,这在某些情况下很重要。 这就是为什么以下代码在psYchotic的答案中显示的实现:
if (numer >= 0 && result.rem < 0)
{
++result.quot;
result.rem -= denom;
}
%可能会返回否定答案,而div()始终返回非负余数。
检查WikiPedia entry,特别是“div总是向0舍入,与C中的普通整数除法不同,其中负数舍入取决于实现。”
答案 3 :(得分:6)
div()
填写了C99之前的需求:可移植性
Pre C99,a / b
与负操作数的商的舍入方向取决于实现。使用div()
时,舍入方向不是可选的,但指定朝向0. div()
提供统一的便携式除法。 secondary 的使用是计算商和余数时所需代码的潜在效率。
使用C99及更高版本,div()
和/
指定相同的舍入方向,并且更好的编译器优化了附近的a/b
和a%b
代码,因此需求已减少。
这是div()
和的令人信服的理由,它解释了C规范中缺少udiv_t udiv(unsigned numer, unsigned denom)
:a/b
与unsigned
的实现相关结果的问题即使在C99之前,{{1}}也不存在负操作数。
答案 4 :(得分:1)
如果您需要两个值,则花费更少的时间。 CPU在执行除法时始终计算余数和商。 如果使用“/”一次和“%”一次,cpu将计算两次数。
(原谅我可怜的英语,我不是本地人)
答案 5 :(得分:1)
可能是因为在许多处理器上,div指令产生两个值,并且您始终可以依靠编译器来识别相同输入上的相邻/和%运算符可以合并为一个操作。