C++位運算


位運算應用口訣 
清零取反要用與,某位置一可用或 
若要取反和交換,輕輕松松用異或 
移位運算 
要點 1 它們都是雙目運算符,兩個運算分量都是整形,結果也是整形。 
    2 " < <" 左移:右邊空出的位上補0,左邊的位將從字頭擠掉,其值相當於乘2。 
    3 ">>"右移:右邊的位被擠掉。對於左邊移出的空位,如果是正數則空位補0,若為負數,可能補0或補1,這取決於所用的計算機系統。 
    4 ">>>"運算符,右邊的位被擠掉,對於左邊移出的空位一概補上0。 
位運算符的應用 (源操作數s 掩碼mask) 
(1) 按位與-- & 
1 清零特定位 (mask中特定位置0,其它位為1,s=s&mask) 
2 取某數中指定位 (mask中特定位置1,其它位為0,s=s&mask) 
(2) 按位或-- | 
    常用來將源操作數某些位置1,其它位不變。 (mask中特定位置1,其它位為0 s=s|mask) 
(3) 位異或-- ^ 
1 使特定位的值取反 (mask中特定位置1,其它位為0 s=s^mask) 
2 不引入第三變量,交換兩個變量的值 (設 a=a1,b=b1) 
    目 標          操 作              操作后狀態 
a=a1^b1        a=a^b              a=a1^b1,b=b1 
b=a1^b1^b1      b=a^b              a=a1^b1,b=a1 
a=b1^a1^a1      a=a^b              a=b1,b=a1 
二進制補碼運算公式: 
-x = ~x + 1 = ~(x-1) 
~x = -x-1 
-(~x) = x+1 
~(-x) = x-1 
x+y = x - ~y - 1 = (x|y)+(x&y) 
x-y = x + ~y + 1 = (x|~y)-(~x&y) 
x^y = (x|y)-(x&y) 
x|y = (x&~y)+y 
x&y = (~x|y)-~x 
x==y:    ~(x-y|y-x) 
x!=y:    x-y|y-x 
x < y:    (x-y)^((x^y)&((x-y)^x)) 
x <=y:    (x|~y)&((x^y)|~(y-x)) 
x < y:    (~x&y)|((~x|y)&(x-y))//無符號x,y比較 
x <=y:    (~x|y)&((x^y)|~(y-x))//無符號x,y比較 
應用舉例 
(1) 判斷int型變量a是奇數還是偶數            
a&1  = 0 偶數 
      a&1 =  1 奇數 
(2) 取int型變量a的第k位 (k=0,1,2……sizeof(int)),即a>>k&1 
(3) 將int型變量a的第k位清0,即a=a&~(1 < <k) 
(4) 將int型變量a的第k位置1, 即a=a|(1 < <k) 
(5) int型變量循環左移k次,即a=a < <k|a>>16-k  (設sizeof(int)=16) 
(6) int型變量a循環右移k次,即a=a>>k|a < <16-k  (設sizeof(int)=16) 
(7)整數的平均值 
對於兩個整數x,y,如果用 (x+y)/2 求平均值,會產生溢出,因為 x+y 可能會大於INT_MAX,但是我們知道它們的平均值是肯定不會溢出的,我們用如下算法: 
int average(int x, int y)  //返回X,Y 的平均值 
{    
    return (x&y)+((x^y)>>1); 

(8)判斷一個整數是不是2的冪,對於一個數 x >= 0,判斷他是不是2的冪 
boolean power2(int x) 

    return ((x&(x-1))==0)&&(x!=0); 

(9)不用temp交換兩個整數 
void swap(int x , int y) 

    x ^= y; 
    y ^= x; 
    x ^= y; 

(10)計算絕對值 
int abs( int x ) 

int y ; 
y = x >> 31 ; 
return (x^y)-y ;        //or: (x+y)^y 

(11)取模運算轉化成位運算 (在不產生溢出的情況下) 
        a % (2^n) 等價於 a & (2^n - 1) 
(12)乘法運算轉化成位運算 (在不產生溢出的情況下) 
        a * (2^n) 等價於 a < < n 
(13)除法運算轉化成位運算 (在不產生溢出的情況下) 
        a / (2^n) 等價於 a>> n 
        例: 12/8 == 12>>3 
(14) a % 2 等價於 a & 1        
(15) if (x == a) x= b; 
            else x= a; 
        等價於 x= a ^ b ^ x; 
(16) x 的 相反數 表示為 (~x+1) 

(17)求x轉化為二進制之后包含1的數量

    int count = 0;

    while(x)

  {

    count++;

    x = x & (x - 1);

    }

 最后得到的count 即為x轉化為二進制之后包含1的數量


實例 

    功能              |          示例            |    位運算 
----------------------+---------------------------+-------------------- 
去掉最后一位            | (101101->10110)              | x >> 1 
在最后加一個0          | (101101->1011010)           | x < < 1 
在最后加一個1          | (101101->1011011)           | x < < 1+1 
把最后一位變成1       | (101100->101101)             | x | 1 
把最后一位變成0       | (101101->101100)             | x | 1-1 
最后一位取反            | (101101->101100)             | x ^ 1 
把右數第k位變成1      | (101001->101101,k=3)      | x | (1 < < (k-1)) 
把右數第k位變成0      | (101101->101001,k=3)      | x & ~ (1 < < (k-1)) 
右數第k位取反          | (101001->101101,k=3)       | x ^ (1 < < (k-1)) 
取末三位                 | (1101101->101)                 | x & 7 
取末k位                  | (1101101->1101,k=5)         | x & ((1 < < k)-1) 

取右數第k位                | (1101101->1,k=4)              | x >> (k-1) & 1 

把末k位變成1              | (101001->101111,k=4)        | x | (1 < < k-1) 
末k位取反                  | (101001->100110,k=4)         | x ^ (1 < < k-1) 
把右邊連續的1變成0     | (100101111->100100000)     | x & (x+1) 
把右起第一個0變成1     | (100101111->100111111)     | x | (x+1) 
把右邊連續的0變成1     | (11011000->11011111)         | x | (x-1) 
取右邊連續的1            | (100101111->1111)              | (x ^ (x+1)) >> 1 
去掉右起第一個1的左邊 | (100101000->1000)              | x & (x ^ (x-1)) 
判斷奇數       (x&1)==1 
判斷偶數 (x&1)==0       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM