位運算主要知識

什麼是位運算? 

程序中的所有數在計算機內存中都是以二進制的形式儲存的。位運算說穿了,就是直接對整數在內存中的二進制位進行操作。 
C++提供了6種位運算符來進行位運算操作:
&      按位與
|      按位或
^      按位異或
~      按位取反
<<     左移(左邊消失,右邊補0)
>>     右移(右邊消失,左邊補符號位)
位運算的操作數是整數類型或字符型.

按位與&運算

將參與運算的兩操作數各自對應的二進制位進行與操作。例如:6的二進制是110,11的二進制是1011,那麼6 & 11的結果就是2 
    110
&  1011
------------
   0010  -->  2
& 運算常常用來將某變量的某些位清0,而保留其它位不變。例如,需要將int型變量n的低8位全置成0,而其餘位不變,則用:
       n = n & 0xFFFFFF00
& 也常用於二進制取位操作,例如一個數 & 1的結果就是取二進制的最末位。如果要判斷n的第8位(從右往左,從1開始數)是否是1,則用:
             if (n & 0x80 == 0x80)  語句
附註:int型是32個二進制位,16進制整數每個數字代表4個二進制位,故16進制int型常量最多是8位。


按位或|運算

 |運算通常用於二進制特定位上的強制置1,例如一個數或 1的結果就是把二進制最末位強行變成1。
      110
|    1011
------------
     1111 -->  15

按位異或^運算

0^0=0  0^1=1  1^1=0
^運算通常用於對二進制的特定一位進行取反操作.例如n^0xff就使得n的最後8位取反。
    110
^  1011
-----------
   1101   -->  13
^運算的特點是:如果a^b==c,則有a^c==b和c^b==a
^可用於簡單加密,參見顧森BLOG


左移<<運算

 a << b就表示把a轉爲二進制後左移b位(在後面添b個0)。例如100的二進制爲1100100,而110010000轉成十進制是400,那麼100 << 2 = 400。可以看出,a << b的值實際上就是a乘以2的b次方,因爲在二進制數後添一個0就相當於該數乘以2(這樣做要求保證高位的1不被移出)。
通常認爲a << 1比a * 2更快,因爲前者是更底層一些的操作。因此程序中乘以2的操作請儘量用左移一位來代替。
定義常量時可以用<<運算。你可以方便地用(1 << 16) - 1來表示65535。很多算法和數據結構要求數據規模必須是2的冪,此時可以用<<來定義MAXN等常量。


右移>>運算

a >> b表示二進制右移b位(去掉末b位)。
當a是正整數時,a>>b等價於a/(2的b次方)
當a是負整數時,a>>b並不等價與a/(2的b次方),而是等於a/(2的b次方)上取整。
如a=-9
cout<<a/2; //輸出-4.
cout<<(a>>1); //輸出-5.

我們也經常用>> 1來代替div 2,比如二分查找、堆的插入操作等等。
用>>代替除法運算可以使程序效率大大提高。最大公約數的二進制算法用除以2操作來代替慢得出奇的%運算,效率可以提高60%。
二進制求最大公約數原理。
若a<b         gcd(a,b)=gcd(b,a)
若a、b都是偶數,則gcd(a,b)=2*gcd(a/2,b/2)
若a是奇數、b是偶數,則gcd(a,b)=gcd(a,b/2)
若a、b都是奇數,則gcd(a,b)=gcd((a-b)/2,b)


位運算的簡單應用 






整數類型的儲存 

計算機用0x0000到0x7FFF依次表示0到32767的數,剩下的0x8000到0xFFFF依次表示-32768到-1的數。32位有符號整數的儲存方式也是類似的。稍加註意你會發現,二進制的第一位是用來表示正負號的,0表示正,1表示負。這裏有一個問題:0本來既不是正數,也不是負數,但它佔用了0x0000的位置,因此有符號的整數類型範圍中正數個數比負數少一個。對一個有符號的數進行~運算後,最高位的變化將導致正負顛倒,並且數的絕對值會差1。也就是說,~ a實際上等於-a-1。這種整數儲存方式叫做“補碼”。
換言之,~a+1 = -a,那麼a & -a得到什麼?
得到a的右數第1位爲1的數,這個操作可用來枚舉a中爲1的位,這在位操作中有較多應用。

發佈了80 篇原創文章 · 獲贊 134 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章