2014-03-04 85 views
1

我有一個功能來切換每個十六進制數字的第0位和第3位,但它使用26操作。我只是想把它減少到1到25個操作。只能使用按位操作! 〜&^| + < < >>。減少操作次數

int swap30(int x) { 
    int m = 0b10001000 << 24; 
    int m1 = 0b10001000 << 16; 
    int m2 = 0b10001000 << 8; 
    int m3 = 0b10001000; 
    int mask1 = m | m1 | m2 | m3; 

    int z = 0b01100110 << 24; 
    int z1 = 0b01100110 << 16; 
    int z2 = 0b01100110 << 8; 
    int z3 = 0b01100110; 
    int mask2 = z | z1 | z2 | z3; 

    int y = 0b00010001 << 24; 
    int y1 = 0b00010001 << 16; 
    int y2 = 0b00010001 << 8; 
    int y3 = 0b00010001; 
    int mask3 = y | y1 | y2 | y3; 

    int three = x & mask1; 
    int stable = x & mask2; 
    int one = x & mask3; 
    int final2 = ((three >> 3) & mask3) | stable | (one << 3); 
    return final2; 
} 
+1

這應該寧可在[http://codereview.stackexchange.com/](http://codereview.stackexchange.com/) – AntonH

+0

編譯器將可能預計算'mask1','mask2'和'mask3',所以你不會在運行時產生這些命中。 –

+0

這個問題似乎是題外話題,因爲它屬於Code Review。 –

回答

3
return (x & 0x66666666) | ((x >> 3) & 0x11111111) | ((x & 0x11111111) << 3); 
+0

優雅而有效。 – keshlam

0
  1. 移動低位到高位和屏蔽掉產生的比特。
  2. 將高位移到低位並掩蓋結果位。
  3. 將所有尚未移動的位屏蔽掉。
  4. 將結果與OR組合。

代碼:

unsigned SwitchBits(unsigned n) { 
    return ((n << 3) & 0x88888888) | ((n >> 3) & 0x11111111) | (n & 0x66666666); 
} 

Alternativly,如果你想成爲非常聰明。它可以用兩個較少的操作來完成,但由於指令之間的某些依賴性,這可能實際上並不快。

  1. 移動高位與低位
  2. XOR記錄在低比特一個0如果高的低比特是相同的,並且如果1它們是不同的對準。
  3. 由此,只掩蓋每個半字節的低位。
  4. 由此乘以9,這將保持原來的低位,並將其複製到高位。
  5. 由此,XOR與原始值。在高位和低位相同的情況下,不會發生正確的改變。如果它們不同,它們將被有效地交換。

代碼:

unsigned SwitchBits(unsigned n) { 
    return ((((n >> 3)^n) & 0x11111111) * 0x9)^n; 
}