反轉比特位(文章最后有干貨)【轉】


轉自:https://blog.csdn.net/wuxianglonghaohao/article/details/21602305

http://www.newhottopic.com/2014/03/20/reverse-bits/

 

把一個無符號整數的比特位反轉順序。
有很多種方法來實現這個。我們這里給出一個算法:通過異或運算來交換,然后用分治方法來優化它。

提示:

你怎么把第i個和第j個位置的bit給交換了呢?如果你能用異或來實現,試着給出算法。

異或交換的小技巧:

如果一共有n個bit,反轉它可以通過最少n/2次交換,最多n次交換來完成。技巧就在於實現一個交換函數swapBits(i,j),用來交換位置在i和j的兩個bit。你應該還記得異或運算:0 ^ 0 == 0, 1 ^ 1 == 0, 0 ^ 1 == 1, 和 1 ^ 0 == 1。
我們只要在第i位和第j位的bit不同時交換就行了。我們用異或來檢測這兩位bit是否相同。然后我們還需要切換這兩個位置的bit值,我們可以再次用異或來完成操作。通過異或,兩個位置的值都可以被切換了。
  1.  
    typedef unsigned int uint;
  2.  
    uint swapBits(uint x, uint i, uint j) {
  3.  
    uint lo = ((x >> i) & 1);
  4.  
    uint hi = ((x >> j) & 1);
  5.  
    if (lo ^ hi) {
  6.  
    x ^= (( 1U << i) | (1U << j));
  7.  
    }
  8.  
    return x;
  9.  
    }
  10.  
     
  11.  
    uint reverseXor(uint x) {
  12.  
    uint n = sizeof(x) * 8;
  13.  
    for (uint i = 0; i < n/2; i++) {
  14.  
    x = swapBits(x, i, n-i -1);
  15.  
    }
  16.  
    return x;
  17.  
    }
 

(譯者注:上面的其中一行代碼:x ^= ((1U < < i) | (1U << j));是為了切換兩個位置的bit值,可以看個例子:x = 1001,–> x ^= ((1U < < 1) | (1U << 3)) –> x = 1001 ^ (1010) –> x = 0011 )

用這種異或方法來反轉bit位的時間復雜度是O(n),n是傳入的無符號整數的比特位數。

分而治之:

記得歸並排序是怎么做的吧?讓我們看一下當n=8(一字節)時是怎么樣的:
  1.  
    01101001
  2.  
    / \
  3.  
    0110 1001
  4.  
    / \ / \
  5.  
    01 10 10 01
  6.  
    /\ /\ /\ /\
  7.  
    0 1 1 0 1 0 0 1
 
第一步是交換所有奇數和偶數位置的bit。然后交換連續成對的bit,依此類推……
因此,一共只要log(n)次操作就能完成。
下面的代碼展示了一個特定的當n==32時的例子——當然,它也能很簡單的去適配當n更大時的情況。
  1.  
    uint reverseMask(uint x) {
  2.  
    assert( sizeof(x) == 4); // special case: only works for 4 bytes (32 bits).
  3.  
    x = ((x & 0x55555555) << 1) | ((x & 0xAAAAAAAA) >> 1);
  4.  
    x = ((x & 0x33333333) << 2) | ((x & 0xCCCCCCCC) >> 2);
  5.  
    x = ((x & 0x0F0F0F0F) << 4) | ((x & 0xF0F0F0F0) >> 4);
  6.  
    x = ((x & 0x00FF00FF) << 8) | ((x & 0xFF00FF00) >> 8);
  7.  
    x = ((x & 0x0000FFFF) << 16) | ((x & 0xFFFF0000) >> 16);
  8.  
    return x;
  9.  
    }

 

小記:

這不是反轉bit位的唯一方法,也不是效率最高的。你想要探索更多關於反轉bit位的算法/靈感,請訪問這里: Bit Twiddling Hacks(譯者注:該鏈接里真的很多好東東)。
英文原文在 這里


免責聲明!

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



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