位運算的應用

 

  • 一.邏輯運算符  算法

    1.& 位與運算  spa

     1) 運算規則  開發

    位與運算的實質是將參與運算的兩個數據,按對應的二進制數逐位進行邏輯與運算。例如:int型常量47進行位與運算的運算過程以下:get

    4=0000 0000 0000 0100 &7 =0000 0000 0000 0111= 0000 0000 0000 0100it

    對於負數,按其補碼進行運算。例如:例如:int型常量-47進行位與運算的運算過程以下:-4=1111 1111 1111 1100 &7 =0000 0000 0000 0111= 0000 0000 0000 0100io

    2) 典型應用  table

    (1) 清零  效率

    清零:快速對某一段數據單元的數據清零,即將其所有的二進制位爲0。例如整型數a=321對其所有數據清零的操做爲a=a&0x0 321=0000 0001 0100 0001 &0=0000 0000 0000 0000變量

    = 0000 0000 0000 0000循環

    (2) 獲取一個數據的指定位 

    獲取一個數據的指定位。例如得到整型數a=的低八位數據的操做爲a=a&0xFF321=

    0000 0001 0100 0001 & 0xFF =0000 0000 1111 11111

    = 0000 0000 0100 0001

    得到整型數a=的高八位數據的操做爲a=a&0xFF00==a&0XFF00==

    321=0000 0001 0100 0001 & 0XFF00=1111 1111 0000 0000

    = 0000 0001 0000 0000

    (3)保留數據區的特定位 

    保留數據區的特定位。例如得到整型數a=的第7-8位(從0開始)位的數據操做爲: 110000000

    321=0000 0001 0100 0001 & 384=0000 0001 1000 0000

    =0000 0001 0000 0000

    2. | 位或運算 

    1) 運算規則 

    位或運算的實質是將參與運算的兩個數據,按對應的二進制數逐位進行邏輯或運算。例如:int型常量57進行位或運算的表達式爲5|7,結果以下:5= 0000 0000 0000 0101

    | 7= 0000 0000 0000 0111=0000 0000 0000 0111

    2) 主要用途 

    (1) 設定一個數據的指定位。例如整型數a=321,將其低八位數據置爲1的操做爲a=a|0XFF321= 0000 0001 0100 0001 | 0000 0000 1111 1111=0000 0000 1111 1111

    邏輯運算符||與位或運算符|的區別 

    條件「或」運算符 (||) 執行 bool 操做數的邏輯「或」運算,但僅在必要時才計算第二個操做數。 x || y , x | y 不一樣的是,若是 x true,則不計算 y(由於不論 y 爲什麼值,「或」操做的結果都爲 true)。這被稱做爲「短路」計算。

    3. ^ 位異或 

     1) 運算規則 

    位異或運算的實質是將參與運算的兩個數據,按對應的二進制數逐位進行邏輯異或運算。只有當對應位的二進制數互斥的時候,對應位的結果才爲真。例如:int型常量57進行位異或運算的表達式爲5^7,結果以下:5=0000 0000 0000 0101^7=0000 0000 0000 0111

    = 0000 0000 0000 0010

    2) 典型應用 

     (1)定位翻轉 

    定位翻轉:設定一個數據的指定位,將1換爲00換爲1。例如整型數a=321,,將其低八位數據進行翻位的操做爲a=a^0XFF;

    (2)數值交換 

    數值交換。例如a=3,b=4。在例11-1中,無須引入第三個變量,利用位運算便可實現數據交換。如下的操做能夠實現a,b兩個數據的交換:

    a=a^b;

    b=b^a;

    a=a^b;

    4~ 位非 

    位非運算的實質是將參與運算的兩個數據,按對應的二進制數逐位進行邏輯非運算。

     

    二.位移運算符

    1.位左移

    左移運算的實質是將對應的數據的二進制值逐位左移若干位,並在空出的位置上填0,最高位溢出並捨棄。例如int a,b;

    a=5;

    b=a<<2;

    則b=20,分析過程以下:

    (a)10=(5)10=(0000 0000 0000 0101)2

    b=a<<2;

    b=(0000 0000 0001 0100)2=(20)10

    從上例能夠看出位運算能夠實現二倍乘運算。因爲位移操做的運算速度比乘法的運算速度高不少。所以在處理數據的乘法運算的時,採用位移運算能夠得到較快的速度。

    提示 將全部對2的乘法運算轉換爲位移運算,可提升程序的運行效率

    2.位右移

    位右移運算的實質是將對應的數據的二進制值逐位右移若干位,並捨棄出界的數字。若是當前的數爲無符號數,高位補零。例如:

    int (a)10=(5)10=(0000 0000 0000 0101)2

    b=a>>2;

    b=(0000 0000 0000 0001)2=(1)10

    若是當前的數據爲有符號數,在進行右移的時候,根據符號位決定左邊補0仍是補1。若是符號位爲0,則左邊補0;可是若是符號位爲1,則根據不一樣的計算機系統,可能有不一樣的處理方式。能夠看出位右移運算,能夠實現對除數爲2的整除運算。

    提示 將全部對2的整除運算轉換爲位移運算,可提升程序的運行效率

    3.複合的位運算符

    在C語言中還提供複合的位運算符,以下:

    &=、!=、>>=、<<=和^=

    例如:a&=0x11等價於 a= a&0x11,其餘運算符以此類推。

    不一樣類型的整數數據在進行混合類型的位運算時,按右端對齊原則進行處理,按數據長度大的數據進行處理,將數據長度小的數據左端補0或1。例如char a與int b進行位運算的時候,按int 進行處理,char a轉化爲整型數據,並在左端補0。

    補位原則以下:

    1) 對於有符號數據:若是a爲正整數,則左端補0,若是a 爲負數,則左端補1。

    2) 對於無符號數據:在左端補0。

    4.例子

    例11-2 得到一個無符號數據從第p位開始的n位二進制數據。假設數據右端對齊,第0位二進制數在數據的最右端,得到的結果要求右對齊。

    #include

    /*getbits:得到從第p位開始的n位二進制數 */

    unsigned int getbits(unsigned int x, unsigned int p, unsigned n)

    {

    unsigned int a;

    unsigned int b;

    a=x>>(p+1);

    b=~(~0<<n);< n);<="" p="">

    return a&b;

    }

    提示在某一平臺進行程序開發時,首先要求瞭解此係統的基本數據類型的有效範圍,對涉及的位運算進行評估,特別是要對邊界數據進行檢測,確保計算正確。





  • (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)

    #include <stdio.h>//設置x的第y位爲1 #define setbit(x,y) (x)|=(1<<(y-1))//獲得x的第y位的值 #define BitGet(Number,pos) ((Number)>>(pos-1)&1)//打印x的值 #define print(x) printf("%d\n",x)//將整數(4個字節)循環右移動k位 #define Rot(a,k) ((a)<<(k)|(a)>>(32-k))//判斷a是否爲2的冪次數 #define POW2(a) ((((a)&(a-1))==0)&&(a!=0)) #define OPPX(x) (~(x)+1)//返回X,Y 的平均值int average(int x, int y) {    return (x&y)+((x^y)>>1); }//判斷a是否爲2的冪次數bool power2(int x) {     return ((x&(x-1))==0)&&(x!=0); }//x與y互換void swap(int& x , int& y) {      x ^= y;      y ^= x;      x ^= y; }int main() {int a=0x000D; print(a);int b=BitGet(a,2); print(b); setbit(a,2); print(a); print(BitGet(a,2));int c=Rot(a,33); print(c); print(BitGet(c,5)); printf("8+5=%d\n",average(8,692));int i;for (i=0;i<1000;i++) {    if (POW2(i))//調用power2(i)     {      printf("%-5d",i);     } } printf("\n");int x=10,y=90; swap(x,y); print(x); print(y); print(OPPX(-705));return 0; }

相關文章
相關標籤/搜索