我在想,如果我想将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);
或者
也许有一个神奇的函数可以同时给出两者?
我在想,如果我想将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
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. */
idivl
指令,并将结果存储在 eax 和 edx 中。如果它没有这样做,我会感到震惊的。 - Fred Larsonidivl
指令,但是通过使用-O1
或更高级别的优化,您将获得一个指令。正如手册所说,“没有任何优化选项…语句是独立的”。 - Tom Zychstd::div
返回一个结构体,其中包含商和余数。
/
和%
运算符,你将会有代码重复或需要额外的变量来存放被除数和除数,并且缺乏经验的读者可能会问:这段代码会被优化吗?使用std::div
能够使代码更加清晰,减少歧义和冗余。通过使用结构化绑定,可以非常优雅地实现:const auto [q, r] = std::div(divisor, dividend);
- pasbivoid 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
/=
,您可能需要使用临时变量来保持除法优先。 - AnnanFay测试div()和组合除法与取模的示例代码。我使用gcc -O3编译了这些代码,必须添加对doNothing的调用以防止编译器将所有内容优化掉(使用除法+取模解决方案的输出将为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
其他条件相同的情况下,最好的解决方案是能够清晰表达您意图的方案。因此:
int totalSeconds = 453;
int minutes = totalSeconds / 60;
int remainingSeconds = totalSeconds % 60;
你提供的三个选项中,div
方法可能是最好的选择。但需要注意的是,div
方法会同时计算这两个值,这一点在其他回答中也有提到。
int div = a / b;
int mod = a % b;
int div = a / b;
int mod = a - div * b;
你可以使用模数来获取余数。虽然@cnicutar的答案似乎更简洁/直接。