同樣是同學遇到的面試題,面試官問的原題是如何用移位和加減實現除以3的操作,在此略微擴充一下,實現不帶正負號的整數除法,但是傳回值也為無符號整型。
方法一:類似小學學習的除法運算,從高位開始減去除數,此處用除數左移到跟被除數對齊,在相減之前商也同樣需要左移,代碼如下。
#include <iostream>using namespace std;unsigned int divide(unsigned int a, unsigned int b){if(0 == b)__asm int 0unsigned int c = 1, d = 0, _b = b;while(a >= b){c <<= 1;b <<= 1;}b >>= 1;c >>= 1;while(b >= _b){if(a >= b){a -= b;d += c;}b >>= 1;c >>= 1;}return d;}int main(){unsigned int in, out;cin>>in;cin>>out;cout<<divide(in, out)<<endl;return 0;}
方法二:用被除數減去除數,每減成功一次商的結果加1,其它代碼不變,divide函數代碼改為如下。
unsigned int divide(unsigned int a, unsigned int b){if(0 == b)__asm int 0unsigned int c = 0;while(a >= b){a -= b;c++;}return c;}
方法三:利用魔數。代碼如下。
#include <iostream>using namespace std;int divide3(int a){return ((__int64)a * 0xAAAAAAAB) >>33;}int main(){int in;cin>>in;cout<<divide3(in)<<endl;return 0;}
其中方法三中的魔數的原理是為了用乘法實現32位被除數的除法運算,編譯器會為被除數乘上一個32位的倒數,就形成了一個64位的數,其中低32位是餘數,高32位為我們需要的結果,以下是一些常用的魔數,例如0xAAAAAAAB就代表2/3,0xCCCCCCCD代表4/5等等,具體可以在網上搜尋相關內容。利用魔數除以5的代碼如下。
#include <iostream>using namespace std;int divide5(int a){return ((__int64)a * 0xCCCCCCCD) >>34;}int main(){int in;cin>>in;cout<<divide5(in)<<endl;return 0;}