在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
)。
总之,如果你关心挤出最后一点性能,这可能是你首选的函数,特别是如果你的平台上的优化器不那么先进。这通常适用于嵌入式平台。否则,使用你认为更易读的方式。
/
和 %
。 - Ben Voigtdiv()
函数,因此它仍然存在。 - Jonathan Grynspandiv() 函数返回一个结构体,其中包含第一个参数(被除数)除以第二个参数(除数)的商和余数。这个函数有四种变体:
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;
}
div
指定为“在单个操作中计算numer / denom和numer%denom”。自C99以来,不再需要if(numer> = 0 && result.rem <0)
块。 - chux - Reinstate Monicadiv()的语义与%和/的语义不同,在某些情况下这很重要。这就是为什么在psYchotic的答案中展示了以下代码的实现方式:
if (numer >= 0 && result.rem < 0)
{
++result.quot;
result.rem -= denom;
}
% 可能返回一个负数,而div()总是返回一个非负余数。
请查看维基百科条目,特别是“div始终向0舍入,不像C语言中普通的整数除法,其中对于负数的舍入取决于具体实现。”
numer < 0
,则余数为负数。2)自C11以来,内置的/
和%
保证向零截断,因此div
被定义为与/
和%
相同。 - Yakov Galkaprintf("%d\n", div(-7,2).rem);
,我预计代码将返回-1
。 - chux - Reinstate Monicadiv()
填补了C99之前的需求:可移植性
在C99之前,使用负数操作数计算a/b
的商的舍入方向依赖于实现。使用div()
,舍入方向不是可选的,而是被指定为向0舍入。 div()
提供了统一的可移植除法。一个次要的用途是当代码需要同时计算商和余数时,可以提高效率。
随着C99及以后版本的到来,div()
和/
指定相同的舍入方向,并且更好的编译器优化了附近的a/b
和a%b
代码,因此需求已经减少。
div()
的重要原因,也解释了C规范中缺少udiv_t udiv(unsigned numer, unsigned denom)
的原因:在使用unsigned
时,即使在C99之前,使用负操作数进行a/b
运算所产生的实现相关结果问题是不存在的。请注意保留HTML标签。可能是因为在许多处理器上,div指令会产生两个值,并且您可以始终依靠编译器识别相邻的/和%运算符在相同输入上可以合并为一个操作。
如果您需要两个值,使用除法运算符和取模运算符可以节省时间。 当执行除法运算时,CPU总是同时计算余数和商。 如果使用一次“/”和一次“%”,CPU将会对这两个数字进行两次计算。
(请原谅我的英语不好,我不是以英语为母语的人)
div()
指定的方式提供商和余数,而无需诉诸“额外的检查”。这是一个平台相关的问题。可能需要或不需要检查。 - chux - Reinstate Monica