分類:語言2012-12-08 09:4530791人閱讀評論(122)收藏舉報
一提起位運算季俩,人們往往想到它的高效性,無論是嵌入式編程還是優(yōu)化系統(tǒng)的核心代碼违寞,適當?shù)倪\用位運算總是一種迷人的手段翎卓,或者當您求職的時候契邀,在代碼中寫入適當?shù)奈贿\算也會讓您的程序增加一絲亮點,最初當我讀《編程之美》求“1的數(shù)目”時失暴,我才開始覺得位運算是如此之美坯门,后來讀到?《Hacker's Delight》,感慨到Henry S.Warren把位運算運用的如此神出鬼沒逗扒,很多程序都十分精妙古戴,我覺得在一個普通的程序中大量運用這樣的代碼的人簡直是瘋了!但掌握簡單的位運算技巧還是必要的矩肩,所以今天寫這篇博文把我積累的一些位運算技巧分享給大家现恼,這些技巧不會是如求“1的數(shù)目”的技巧,是最基本的一行位運算技巧!
Welcome To MyBitTricks
[cpp]view plaincopy
intgetMaxInt(){
return(1?<<?31)?-?1;//2147483647叉袍,?由于優(yōu)先級關(guān)系始锚,括號不可省略
}
[cpp]view plaincopy
intgetMaxInt(){
return~(1?<<?31);//2147483647
}
[cpp]view plaincopy
intgetMaxInt(){//有些編譯器不適用
return(1?<<?-1)?-?1;//2147483647
}
[java]view plaincopy
intgetMaxInt(){
return((unsignedint)?-1)?>>1;//2147483647
}
[cpp]view plaincopy
intgetMinInt(){
return1?<<?31;//-2147483648
}
[cpp]view plaincopy
intgetMinInt(){//有些編譯器不適用
return1?<<?-1;//-2147483648
}
[cpp]view plaincopy
longgetMaxLong(){
return((unsignedlong)?-?1)?>>?1;//2147483647
}
[java]view plaincopy
longgetMaxLong(){
return((long)1<<127)?-1;//9223372036854775807
}
獲得long最小值,和其他類型的最大值喳逛,最小值同理.
[cpp]view plaincopy
intmulTwo(intn){//計算n*2
returnn?<<?1;
}
[cpp]view plaincopy
intdivTwo(intn){//負奇數(shù)的運算不可用
returnn?>>?1;//除以2
}
[cpp]view plaincopy
intmulTwoPower(intn,intm){//計算n*(2^m)
returnn?<<?m;
}
[cpp]view plaincopy
intdivTwoPower(intn,intm){//計算n/(2^m)
returnn?>>?m;
}
[java]view plaincopy
booleanisOddNumber(intn){
return(n?&1)?==1;
}
[cpp]view plaincopy
voidswap(int*a,int*b){
(*a)?^=?(*b)?^=?(*a)?^=?(*b);
}
[java]view plaincopy
a?^=?b;
b?^=?a;
a?^=?b;
10.取絕對值(某些機器上,效率比n>0 ?? ?n:-n 高)
[cpp]view plaincopy
intabs(intn){
return(n?^?(n?>>?31))?-?(n?>>?31);
/*?n>>31?取得n的符號润文,若n為正數(shù)姐呐,n>>31等于0,若n為負數(shù)转唉,n>>31等于-1
若n為正數(shù)?n^0=0,數(shù)不變皮钠,若n為負數(shù)有n^-1?需要計算n和-1的補碼,然后進行異或運算赠法,
結(jié)果n變號并且為n的絕對值減1,再減去-1就是絕對值?*/
}
11.取兩個數(shù)的最大值(某些機器上乔夯,效率比a>b ? a:b高)
[cpp]view plaincopy
intmax(inta,intb){
returnb?&?((a-b)?>>?31)?|?a?&?(~(a-b)?>>?31);
/*如果a>=b,(a-b)>>31為0砖织,否則為-1*/
}
[cpp]view plaincopy
intmax(intx,inty){
returnx?^?((x?^?y)?&?-(x?<?y));
/*如果x
、?與0做與運算結(jié)果為0末荐,與-1做與運算結(jié)果不變*/
}
12.取兩個數(shù)的最小值(某些機器上侧纯,效率比a>b ? b:a高)
[cpp]view plaincopy
intmin(inta,intb){
returna?&?((a-b)?>>?31)?|?b?&?(~(a-b)?>>?31);
/*如果a>=b,(a-b)>>31為0,否則為-1*/
}
[cpp]view plaincopy
intmin(intx,inty){
returny?^?((x?^?y)?&?-(x?<?y));
/*如果x
與0做與運算結(jié)果為0甲脏,與-1做與運算結(jié)果不變*/
}
[java]view plaincopy
booleanisSameSign(intx,inty){//有0的情況例外
return(x?^?y)?>=0;//?true?表示?x和y有相同的符號眶熬,?false表示x,y有相反的符號块请。
}
[cpp]view plaincopy
intgetFactorialofTwo(intn){//n?>?0
return2?<<?(n-1);//2的n次方
}
[java]view plaincopy
booleanisFactorialofTwo(intn){
returnn?>0??(n?&?(n?-1))?==0:false;
/*如果是2的冪娜氏,n一定是100...?n-1就是1111....
所以做與運算結(jié)果為0*/
}
[java]view plaincopy
intquyu(intm,intn){//n為2的次方
returnm?&?(n?-1);
/*如果是2的冪,n一定是100...?n-1就是1111....
所以做與運算結(jié)果保留m在n范圍的非0的位*/
}
[java]view plaincopy
intgetAverage(intx,inty){
return(x?+?y)?>>1;
}
[java]view plaincopy
intgetAverage(intx,inty){
return((x?^?y)?>>1)?+?(x?&?y);
/*(x^y)?>>?1得到x墩新,y其中一個為1的位并除以2贸弥,
x&y得到x,y都為1的部分海渊,加一起就是平均數(shù)了*/
}
下面是三個最基本對二進制位的操作
[java]view plaincopy
intgetBit(intn,intm){
return(n?>>?(m-1))?&1;
}
[java]view plaincopy
intsetBitToOne(intn,intm){
returnn?|?(1<<?(m-1));
/*將1左移m-1位找到第m位绵疲,得到000...1...000
n在和這個數(shù)做或運算*/
}
[java]view plaincopy
intsetBitToZero(intn,intm){
returnn?&?~(1<<?(m-1));
/*?將1左移m-1位找到第m位,取反后變成111...0...1111
n再和這個數(shù)做與運算*/
}
另附一些對程序效率上沒有實質(zhì)提高的位運算技巧臣疑,一些也是位運算的常識(面試也許會遇到)
[cpp]view plaincopy
-~n
[cpp]view plaincopy
~-n
[java]view plaincopy
~n?+1;
[java]view plaincopy
(n?^?-1)?+1;
if(x == a) x = b; if(x == b) x = a;
[cpp]view plaincopy
x?=?a?^?b?^?x;
sign函數(shù)盔憨,參數(shù)為n,當n>0時候返回1讯沈,n<0時返回-1郁岩,n=0時返回0
[cpp]view plaincopy
return!!n?-?(((unsigned)n?>>?31)?<<?1);
如果您知道實用的一行位運算技巧請留言,博主不勝感激,還有我總結(jié)的位運算難免有不健壯之處驯用,請您多多批評脸秽。
==================================================================================================
作者:nash_ ?歡迎轉(zhuǎn)載,與人分享是進步的源泉蝴乔!
轉(zhuǎn)載請保留原文地址:http://blog.csdn.net/nash_/article/details/8262185