是否有一个c ++函数(内置或其他)给出整数除法和模块除法结果而不重复操作?

Ada*_*m S 5 c++ integer-division

你可以这样写:

int i = 3;
int k = 2;
int division = i / k;
int remainder = i % k;
Run Code Online (Sandbox Code Playgroud)

似乎认为这将在低级别上要求ALU执行两个视觉操作:一个返回商,一个返回余数.但是,我相信ALU最有可能在一次操作中计算两者.如果是这种情况,这不是最佳效率.

是否有更有效的方法,而不要求CPU计算两次?换句话说,它可以在C++的单个操作中完成吗?

Fer*_*cio 9

实际上,您编写的代码不会生成任何除法指令,因为编译器可以在编译时计算出结果.我写了一个小测试程序并设置编译器(VC++ 10SP1)来生成汇编代码清单.

#include <iostream>

using namespace std;

struct result {
    long quotient, remainder;
};

result divide(long num, long den) {
    result d = { num / den, num % den };
    return d;
}

int main() {
    result d = divide(3, 2);
    d = divide(10, 3);
    cout << d.quotient << " : " << d.remainder << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我必须以这种方式编写它,并明确告诉编译器不要内联任何函数.否则编译器会愉快地优化大部分代码.以下是除法函数的结果汇编代码.

; 8    : result divide(long num, long den) {

  00000 55       push    ebp
  00001 8b ec        mov     ebp, esp

; 9    :     result d = { num / den, num % den };

  00003 99       cdq
  00004 f7 7d 08     idiv    DWORD PTR _den$[ebp]

; 10   :     return d;
; 11   : }

  00007 5d       pop     ebp
  00008 c3       ret     0
Run Code Online (Sandbox Code Playgroud)

它足够聪明,可以生成单个IDIV指令并使用它生成的商和余数.现代C和C++编译器在这种优化方面已经非常擅长.除非您遇到性能问题并且已经分析了代码以确定瓶颈在哪里,否则不要试图再次猜测编译器.


orl*_*rlp 5

当然:

int i = 3;
int k = 2;
int division = i / k;
int remainder = i - division * k;
Run Code Online (Sandbox Code Playgroud)

另外,如果你真的想这样做,那么看看div,我怀疑它更快,就像我上面的解决方案一样.


Aln*_*tak 5

ISO C99具有以下ldiv功能:

#include <stdlib.h>

ldiv_t ldiv(long numer, long denom);

The ldiv() function computes the value numer/denom (numerator/denominator).
It returns the quotient and remainder in a structure named ldiv_t that contains
two long members named quot and rem.

无论是在FPU级别还是单一操作我都说不出来.