最好的方法来获得整数除法和余数
C++ Best way to get integer division and remainder
我只是想知道,如果我想用a除以b,并且对结果c和余数都感兴趣(例如,我有几秒,想把它分成分钟和秒),最好的方法是什么?
int c = (int)a / b;
int d = a % b;
或
int c = (int)a / b;
int d = a - b * c;
或
double tmp = a / b;
int c = (int)tmp;
int d = (int)(0.5+(tmp-c)*b);
或
也许有一个神奇的函数可以同时给出两者?
在x86上,余数是除法本身的副产品,所以任何半体面的编译器都应该能够使用它(而不是再次执行div
)。这可能在其他体系结构中也可以实现。
指令:
DIV
src注:无符号除法。将累加器(AX)除以"src"。如果除数是一个字节值,结果放在AL ,余数放在AH。如果除数是一个字值,那么DX:AX除以"src",结果被存储在AX 中,余数存储在DX中。
int c = (int)a / b;
int d = a % b; /* Likely uses the result of the division. */
std::div
返回一个包含结果和余数的结构
至少在x86上,g++ 4.6.1只使用IDIVL,并从单个指令中获取两者。
c++代码:void foo(int a, int b, int* c, int* d)
{
*c = a / b;
*d = a % b;
}
x86代码:__Z3fooiiPiS_:
LFB4:
movq %rdx, %r8
movl %edi, %edx
movl %edi, %eax
sarl $31, %edx
idivl %esi
movl %eax, (%r8)
movl %edx, (%rcx)
ret
测试div()和组合除法&我用gcc -O3编译了这些,我不得不添加对doNothing的调用来阻止编译器优化所有内容(对于除法+ mod解决方案,输出将为0)。
半信半疑:
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
extern doNothing(int,int); // Empty function in another compilation unit
int main() {
int i;
struct timeval timeval;
struct timeval timeval2;
div_t result;
gettimeofday(&timeval,NULL);
for (i = 0; i < 1000; ++i) {
result = div(i,3);
doNothing(result.quot,result.rem);
}
gettimeofday(&timeval2,NULL);
printf("%d",timeval2.tv_usec - timeval.tv_usec);
}
输出:150
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
extern doNothing(int,int); // Empty function in another compilation unit
int main() {
int i;
struct timeval timeval;
struct timeval timeval2;
int dividend;
int rem;
gettimeofday(&timeval,NULL);
for (i = 0; i < 1000; ++i) {
dividend = i / 3;
rem = i % 3;
doNothing(dividend,rem);
}
gettimeofday(&timeval2,NULL);
printf("%d",timeval2.tv_usec - timeval.tv_usec);
}
输出:25
除了前面提到的std::div系列函数之外,还有std::remquo系列函数,返回rem- der并通过传入指针获取quo- client。
[Edit:]看起来std::remquo并没有真正返回商。
在其他条件相同的情况下,最好的解决方案是清楚地表达你的意图。所以:
int totalSeconds = 453;
int minutes = totalSeconds / 60;
int remainingSeconds = totalSeconds % 60;
可能是您提供的三个选项中最好的。但是,正如在其他答案中所指出的那样,div
方法将立即为您计算这两个值。
在32位intel平台上使用64位整数不能信任g++ 4.6.3。A/b通过调用divdi3计算,A %b通过调用moddi3计算。我甚至可以举出一个用这些调用计算a/b和a-b*(a/b)的例子。所以我用c=a/b和a-b*c。
div方法调用计算div结构的函数,但是函数调用在硬件支持整型的平台上似乎效率不高(例如64位的intel/amd平台上的64位整数)。
许多答案建议使用以下代码:
int div = a / b;
int mod = a % b;
然而,值得记住的是,除法与乘法不同,加法的执行时间要长得多(据我所知,与一个时钟周期相比,要花几十倍的时间)。并且,如果需要重复计算mod和div,则值得将两个除法替换为一个除法,一个乘法和一个加法,如下所示:
int div = a / b;
int mod = a - div * b;
您可以使用模数来获得余数。虽然@cnicutar的回答似乎更清晰/更直接。