c++获得整数除法和余数的最佳方法

时间:2021-07-19 07:19:55

I am just wondering, if I want to divide a by b, and am interested both in the result c and the remainder (e.g. say I have number of seconds and want to split that into minutes and seconds), what is the best way to go about it?

我只是想知道,如果我想把a除以b,并且对结果c和余数都感兴趣(比如我有几秒,想把它分成几分钟和几秒),那么最好的方法是什么?

Would it be

int c = (int)a / b;
int d = a % b;

or

int c = (int)a / b;
int d = a - b * c;

or

double tmp = a / b;
int c = (int)tmp;
int d = (int)(0.5+(tmp-c)*b);

or

maybe there is a magical function that gives one both at once?

也许有一种神奇的功能能让你同时拥有两者?

8 个解决方案

#1


72  

On x86 the remainder is a by-product of the division itself so any half-decent compiler should be able to just use it (and not perform a div again). This is probably done on other architectures too.

在x86上,其余的都是除法本身的副产品,所以任何稍微像样的编译器都应该能够使用它(而不是再次执行div)。这可能也是在其他架构上完成的。

Instruction: DIV src

指令:DIV src

Note: Unsigned division. Divides accumulator (AX) by "src". If divisor is a byte value, result is put to AL and remainder to AH. If divisor is a word value, then DX:AX is divided by "src" and result is stored in AX and remainder is stored in DX.

注:无符号除法。用“src”分割蓄电池(AX)。如果divisor是一个字节值,那么结果将被赋值为AL,余数将被赋值为AH。如果divisor是一个单词值,那么DX:AX除以“src”,结果存储在AX中,余数存储在DX中。

int c = (int)a / b;
int d = a % b; /* Likely uses the result of the division. */

#2


58  

std::div returns a structure with both result and remainder.

div返回一个包含结果和余数的结构。

#3


21  

On x86 at least, g++ 4.6.1 just uses IDIVL and gets both from that single instruction.

至少在x86上,g++ 4.6.1只使用IDIVL,并从那条指令中获得这两条指令。

C++ code:

c++代码:

void foo(int a, int b, int* c, int* d)
{
  *c = a / b;
  *d = a % b;
}

x86 code:

x86代码:

__Z3fooiiPiS_:
LFB4:
    movq    %rdx, %r8
    movl    %edi, %edx
    movl    %edi, %eax
    sarl    $31, %edx
    idivl   %esi
    movl    %eax, (%r8)
    movl    %edx, (%rcx)
    ret

#4


7  

Sample code testing div() and combined division & mod. I compiled these with gcc -O3, I had to add the call to doNothing to stop the compiler from optimising everything out (output would be 0 for the division + mod solution).

示例代码测试div()和组合division & mod。我使用gcc -O3编译了这些代码,我必须添加对doNothing的调用,以阻止编译器优化所有内容(division + mod解决方案的输出将为0)。

Take it with a grain of salt:

对它持怀疑态度:

#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);
}

Outputs: 150

输出: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);
}

Outputs: 25

输出:25

#5


5  

In addition to the aforementioned std::div family of functions, there is also the std::remquo family of functions, return the rem-ainder and getting the quo-tient via a passed-in pointer.

除了前面提到的std::div函数家族之外,还有std::remquo函数家族,通过传入指针返回remer并获取quo-tient。

[Edit:] It looks like std::remquo doesn't really return the quotient after all.

看起来好像std: remquo并没有返回商。

#6


3  

All else being equal, the best solution is one that clearly expresses your intent. So:

在其他条件相同的情况下,最好的解决方案是明确表达你的意图。所以:

int totalSeconds = 453;
int minutes = totalSeconds / 60;
int remainingSeconds = totalSeconds % 60;

is probably the best of the three options you presented. As noted in other answers however, the div method will calculate both values for you at once.

这可能是您提供的三个选项中最好的一个。但是,正如其他答案中所指出的,div方法将立即为您计算这两个值。

#7


3  

You cannot trust g++ 4.6.3 here with 64 bit integers on a 32 bit intel platform. a/b is computed by a call to divdi3 and a%b is computed by a call to moddi3. I can even come up with an example that computes a/b and a-b*(a/b) with these calls. So I use c=a/b and a-b*c.

在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。

The div method gives a call to a function which computes the div structure, but a function call seems inefficient on platforms which have hardware support for the integral type (i.e. 64 bit integers on 64 bit intel/amd platforms).

div方法对计算div结构的函数进行调用,但是在对集成类型(即64位intel/amd平台上的64位整数)有硬件支持的平台上,函数调用似乎没有效率。

#8


-4  

You can use a modulus to get the remainder. Though @cnicutar's answer seems cleaner/more direct.

你可以用模数来得到余数。虽然@cnicutar的答案看起来更简洁/更直接。

#1


72  

On x86 the remainder is a by-product of the division itself so any half-decent compiler should be able to just use it (and not perform a div again). This is probably done on other architectures too.

在x86上,其余的都是除法本身的副产品,所以任何稍微像样的编译器都应该能够使用它(而不是再次执行div)。这可能也是在其他架构上完成的。

Instruction: DIV src

指令:DIV src

Note: Unsigned division. Divides accumulator (AX) by "src". If divisor is a byte value, result is put to AL and remainder to AH. If divisor is a word value, then DX:AX is divided by "src" and result is stored in AX and remainder is stored in DX.

注:无符号除法。用“src”分割蓄电池(AX)。如果divisor是一个字节值,那么结果将被赋值为AL,余数将被赋值为AH。如果divisor是一个单词值,那么DX:AX除以“src”,结果存储在AX中,余数存储在DX中。

int c = (int)a / b;
int d = a % b; /* Likely uses the result of the division. */

#2


58  

std::div returns a structure with both result and remainder.

div返回一个包含结果和余数的结构。

#3


21  

On x86 at least, g++ 4.6.1 just uses IDIVL and gets both from that single instruction.

至少在x86上,g++ 4.6.1只使用IDIVL,并从那条指令中获得这两条指令。

C++ code:

c++代码:

void foo(int a, int b, int* c, int* d)
{
  *c = a / b;
  *d = a % b;
}

x86 code:

x86代码:

__Z3fooiiPiS_:
LFB4:
    movq    %rdx, %r8
    movl    %edi, %edx
    movl    %edi, %eax
    sarl    $31, %edx
    idivl   %esi
    movl    %eax, (%r8)
    movl    %edx, (%rcx)
    ret

#4


7  

Sample code testing div() and combined division & mod. I compiled these with gcc -O3, I had to add the call to doNothing to stop the compiler from optimising everything out (output would be 0 for the division + mod solution).

示例代码测试div()和组合division & mod。我使用gcc -O3编译了这些代码,我必须添加对doNothing的调用,以阻止编译器优化所有内容(division + mod解决方案的输出将为0)。

Take it with a grain of salt:

对它持怀疑态度:

#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);
}

Outputs: 150

输出: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);
}

Outputs: 25

输出:25

#5


5  

In addition to the aforementioned std::div family of functions, there is also the std::remquo family of functions, return the rem-ainder and getting the quo-tient via a passed-in pointer.

除了前面提到的std::div函数家族之外,还有std::remquo函数家族,通过传入指针返回remer并获取quo-tient。

[Edit:] It looks like std::remquo doesn't really return the quotient after all.

看起来好像std: remquo并没有返回商。

#6


3  

All else being equal, the best solution is one that clearly expresses your intent. So:

在其他条件相同的情况下,最好的解决方案是明确表达你的意图。所以:

int totalSeconds = 453;
int minutes = totalSeconds / 60;
int remainingSeconds = totalSeconds % 60;

is probably the best of the three options you presented. As noted in other answers however, the div method will calculate both values for you at once.

这可能是您提供的三个选项中最好的一个。但是,正如其他答案中所指出的,div方法将立即为您计算这两个值。

#7


3  

You cannot trust g++ 4.6.3 here with 64 bit integers on a 32 bit intel platform. a/b is computed by a call to divdi3 and a%b is computed by a call to moddi3. I can even come up with an example that computes a/b and a-b*(a/b) with these calls. So I use c=a/b and a-b*c.

在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。

The div method gives a call to a function which computes the div structure, but a function call seems inefficient on platforms which have hardware support for the integral type (i.e. 64 bit integers on 64 bit intel/amd platforms).

div方法对计算div结构的函数进行调用,但是在对集成类型(即64位intel/amd平台上的64位整数)有硬件支持的平台上,函数调用似乎没有效率。

#8


-4  

You can use a modulus to get the remainder. Though @cnicutar's answer seems cleaner/more direct.

你可以用模数来得到余数。虽然@cnicutar的答案看起来更简洁/更直接。