开发者

Is there a c++ function (built-in or otherwise) that gives the integer division and modular division results without repeating the operation?

开发者 https://www.devze.com 2023-04-05 03:36 出处:网络
You could write something like: int i = 3; int k = 2; int division = i / k; int remainder = i % k; It seems as thought this would, on a low level, ask an ALU to perform two vision operations: one r

You could write something like:

int i = 3;
int k = 2;
int division = i / k;
int remainder = i % k;

It seems as thought this would, on a low level, ask an ALU to perform two vision operations: one returning the quotient, and one returning the remainder. However, I believe an ALU would most likely calculate both in a single operation. If that is the case, this is not optimally efficient.

Is there a more efficient way of doing开发者_开发技巧 it, without asking the CPU to calculate twice? In other words, can it be done in a single operation from C++?


Actually, the code you wrote won't generate any division instructions since the compiler can figure out the results at compile time. I wrote a little test program and set the compiler (VC++ 10SP1) to generate an assembly code listing.

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

I had to write it this way and explicitly tell the compiler to not inline any functions. Otherwise the compiler would have happily optimized away most of the code. Here is the resulting assembly code for the divide function.

; 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

It's smart enough to generate a single IDIV instruction and use the quotient and remainder generated by it. Modern C and C++ compilers have gotten really good at this sort of optimization. Unless you have a performance problem and have profiled your code to determine where the bottleneck is, don't try to second guess the compiler.


ISO C99 has the ldiv function:

#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.

Whether at the FPU level that reduces to a single operation I couldn't say.


Sure:

int i = 3;
int k = 2;
int division = i / k;
int remainder = i - division * k;

Also, if you really want to do this, look at div, I doubt it's faster though, just like my above solution.


I'm not aware of anything built-in, but you can simulate it with a multiply instead of a divide:

int division = i / k;
int remainder = i - (division * k);


When you ask yourself, what is fastest, it's usually a good idea to benchmark it (I like to do that). So I took the answers from here and wrote a tiny benchmarking program and threw it at gcc (similar results would be expected for g++ I think) at -O0 (at -O1 he optimises everything away and my benchmark is broken).

I performed 2^28 runs (both i and k running from 1 to 2^14) on my laptop and got the following runtimes:

division = 0;
remainder = 0;
// this test is only there to measure the constant overhead!

1.676s

division = i/k;
remainder = i%k;

24.614s

division = i/k;
remainder = i - division*k;

15.009s

ldiv_t d = ldiv(i,k);
division = d.quot;
remainder = d.rem;

18.845s

As one can see, there is a difference and your best shot is the multiplication approach. The ldiv approach is also okay, but I find it slightly cumbersome compared to the others.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号