[英]C++ Best way to get integer division and remainder
我只是想知道,如果我想将 a 除以 b,并且对结果 c 和其余部分感兴趣(例如,我有秒数并想将其分成分钟和秒),那么最好的方法是什么go 关于它?
可不可能是
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);
或者
也许有一个神奇的 function 可以同时给一个?
在 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() 和组合除法 & mod。 我用 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 -ainder 并通过传入的指针获取quo -tient。
[编辑:]看起来 std::remquo 毕竟并没有真正返回商。
在其他条件相同的情况下,最好的解决方案是明确表达您的意图。 所以:
int totalSeconds = 453;
int minutes = totalSeconds / 60;
int remainingSeconds = totalSeconds % 60;
可能是您提出的三个选项中最好的一个。 但是,正如其他答案中所述, div
方法将同时为您计算这两个值。
您不能相信 g++ 4.6.3 在 32 位英特尔平台上使用 64 位整数。 a/b 是通过调用 divdi3 来计算的,a%b 是通过调用 moddi3 来计算的。 我什至可以想出一个用这些调用计算 a/b 和 ab*(a/b) 的例子。 所以我使用 c=a/b 和 ab*c。
div 方法调用了计算 div 结构的 function,但 function 调用在硬件支持整数类型的平台上似乎效率低下(即 64 位 intel/amd 平台上的 64 位整数)。
许多答案建议使用以下代码:
int div = a / b;
int mod = a % b;
但是,值得记住的是,除法与乘法不同,加法的执行时间要长得多(据我所知,时钟周期是一个时钟周期的几十倍)。 并且,如果需要反复计算mod和div,那么值得用一除一乘一加代替二除,如下:
int div = a / b;
int mod = a - div * b;
您可以使用模数来获得余数。 尽管@cnicutar 的回答似乎更干净/更直接。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.