[英]Is there a c++ function (built-in or otherwise) that gives the integer division and modular division results without repeating the operation?
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. 似乎认为这将在低级别上要求ALU执行两个视觉操作:一个返回商,一个返回余数。 However, I believe an ALU would most likely calculate both in a single operation.
但是,我相信ALU最有可能在一次操作中计算两者。 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? 是否有更有效的方法,而不要求CPU计算两次? In other words, can it be done in a single operation from C++?
换句话说,它可以在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.
我写了一个小测试程序并设置编译器(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;
}
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. 它足够聪明,可以生成单个IDIV指令并使用它生成的商和余数。 Modern C and C++ compilers have gotten really good at this sort of optimization.
现代C和C ++编译器在这种优化方面已经非常擅长。 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: 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.
Whether at the FPU level that reduces to a single operation I couldn't say. 无论是在FPU级别还是单一操作我都说不出来。
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). 所以我从这里得到了答案并编写了一个很小的基准测试程序,然后把它扔到了
gcc
(我认为g++
会有类似的结果) -O0
(在-O1
他优化了一切,我的基准测试被破坏了)。
I performed 2^28
runs (both i
and k
running from 1
to 2^14
) on my laptop and got the following runtimes: 我在笔记本电脑上执行了
2^28
次运行( i
和k
运行从1
到2^14
)并获得以下运行时:
division = 0;
remainder = 0;
// this test is only there to measure the constant overhead!
1.676s 1.676s
division = i/k;
remainder = i%k;
24.614s 24.614s
division = i/k;
remainder = i - division*k;
15.009s 15.009s
ldiv_t d = ldiv(i,k);
division = d.quot;
remainder = d.rem;
18.845s 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. ldiv
方法也没关系,但我发现它与其他方法相比有点麻烦。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.