位運算技巧總結

        今天在Matrix67大牛的博客上看到了很多位運算的優化技巧,頓感位運算的神奇,現在來我總結一下位運算的神奇用法。

         下面是常見的位運算:

         

    a & b   a和b都是1的位取1,其他都取0。和&&有區別,&&是邏輯運算,返回true或者false
    a  |  b   a和b都是0的位取0,其餘情況都取1。和||有區別,||是邏輯運算,返回true或者false
    a  ^ b   a和b相同的位取0,不同的位取1.
    ~a   a按位取反 一個無符號整形取反等於表示上限減去這個數, 比如12 假設是16位無符號整型,~12就是65535-12=65523
    a << b  a左移b位
    a >> b  a右移b位 

       

        下面是位運算的幾種常見的用法:

       

    把a的末k位變成1           00110001 k=3 => 0110111      a | (1<<k - 1)
    把a的末k位取反         00110001 k=3 => 0110110      a ^ (1<<k -1)
    把a右邊連續的1變成0      00110111 => 00110000    (a +1)&a
    把右邊連續的0變成1        00101111 => 00100000    (a - 1)^a
    取右邊連續的1                00101111 =>  1111            ((a+1) | a) >> 1
    去掉右起第一個1的左邊   00101000 =>  x & (-x) 或者 x & (x ^ (x-1)) 這個在樹狀數組中會用到


        上面這些只是位運算的簡單應用(已經非常強大了),還有一些更加強大的用處,第一個例子是,求一個32bit整數,求它的1的位數,代碼如下:

       

    x := (x and $55555555) + ((x shr 1) and $55555555); 
    x := (x and $33333333) + ((x shr 2) and $33333333); 
    x := (x and $0F0F0F0F) + ((x shr 4) and $0F0F0F0F); 
    x := (x and $00FF00FF) + ((x shr 8) and $00FF00FF); 
    x := (x and $0000FFFF) + ((x shr 16) and $0000FFFF); 

 

        想一下怎麼回事,比如x爲21, 二進制爲10101,把這個數代入代碼中看下,

        第一步 : 10101 & 0101010101010101 + (1010)&0101010101  = 10101

        第二步 :10101&001100110011 + (101)&001100110011 = 10001+1 = 10010

        第三步:   10010&00001111 + 1&00001111 = 10+1= 11

        第四步:   11&11111111 + 0 = 11

        第五步:    11& 11111111 + 0 = 11
        

        上面五步得到了最終結果,答案爲3,到這裏,看出什麼了嗎?這段代碼其實是用了分治的思想,我看了好久,這幾個數字比較令人眼花。 下面讓我來解釋一下。比如這樣一個數字,x32x31x30...x4x3x2x1 ,  第一步之後,變成了   x32x31兩位表示x32和x31的和,x30x29表示x30和x29的和...以此類推。第二步之後,x32x31x30x29四位數字表示x32~x29的和,x28x27x26x25表示x28~x25四位數字的和,以此類推。第五步結束後x32~x1表示x32~x1這32位數字的和。如果你還是不清楚,請看下面這個圖:

 

        如何只用位運算來求一個整數的絕對值呢? 一個正整數x和它的相反數-x的關係是,-x是x的補碼,即-x=(~x)+1.x的絕對值代碼爲 x ^ (~(x >> 31) + 1) + x >> 31,當x爲正數時,x>>31爲0,取反變成-1,再加1變成0,0異或任何數不變;當x爲負數時候,x>>31=1,1取反後加一變成0xFFFFFFFF,異或x之後,x每位取反,取反後再加一剛好是相反數。

       


          先寫到這裏,用到了再加

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章