2017-05-11 4473 views
3

我試過谷歌搜索,但找不到任何可理解的@。@ ... 有人能請外行解釋這個代碼中發生了什麼?什麼是0xaa和0x55在做什麼?

這是「破解編碼採訪」一書中的一個問題。

「寫一個程序,以儘可能少的指令交換整數中的奇數和偶數位(例如,位0和位1被交換,位2和3被交換,依此類推)」。

的方式我這樣做是不涉及位操作,因爲我無法弄清楚如何%\ ...

def swap(n): 

    b = bin(n)[2:] 
    print(b) 
    if len(b)%2 != 0: 
     c = True 
     b = b[0] + b 

    pairs = wrap(b, 2) 
    pairs = [i[::-1] for i in pairs] 
    ans = ''.join(pairs) 

    if c: ans = ans[1:] 
    print(ans) 

但現在我在看他們的回答,我真的不得到它...(不會幫助它不是在Python中):

int swapOddEvenBits(int x) { 
    return (((x & 0xaaaaaaaa) >>> 1) | ((x & 0x55555555) << 1)); 
+1

他們的面具,掩蓋無論是奇數或偶數位。然後他們同時向右移動,並且向左平移,交換它們。 – AntonH

+1

上半部分'''你的'int'與'101010 ...' - 這意味着奇數位保持不變,即使位是'0';標誌不敏感將整個事件轉移一點。第二部分 - '010101 ...'帶有'&'你的'int' - 這意味着偶數位保持不變,奇數位爲零;標誌敏感將整件事向下移動一點。你在正確的位置放置了所有正確的棋子 - 「|」它們在一起。它會幫助你分解代碼並在每一步打印出二進制文件。 –

+0

所以這個問題並不是關於[tag:python]或[tag:java] ... – handle

回答

4

讓我們來分解它。

return (((x & 0xaaaaaaaa) >>> 1) | ((x & 0x55555555) << 1)); 

首先,我們來看看(x & 0xaaaaaaaa)。如果你打破0xaaaaaaaa直到位級別,你最終會得到1010 1010 1010 1010 1010 1010 1010 1010(因爲a,二進制,是1010)。所以(x & 0xaaaaaaaa)是說,只返回每個偶數1x。這稱爲位掩碼。然後,你右移一個位置 - 這就是你如何讓偶數切換位置(所以現在第二位佔據第一位,第四位,第三位等)。

你做同樣的事情與(x & 0x55555555) - 如果你打破它位水平,你最終0101 0101 0101 0101 0101 0101 0101 0101(如5,二進制,是0101)。這掩蓋了x中的所有偶數位,並給出了所有奇數位。然後,將所有位保留爲1.最後,使用or|)運算符組合兩個位序列,這就是您的答案。

例如: 我們拿2456086205.我們把它轉換成二進制並得到1001 0010 0110 0100 1110 0110 1011 1101。現在,我們做(x & 0xaaaaaaaa),並獲得

1001 0010 0110 0100 1110 0110 1011 1101 & 1010 1010 1010 1010 1010 1010 1010 1010

相當於1000 0010 0010 0000 1010 0010 1010 1000。把它移到右邊,你得到0100 0001 0001 0000 0101 0001 0101 0100

現在,做(x & 0x55555555),並獲得

1001 0010 0110 0100 1110 0110 1011 1101 & 0101 0101 0101 0101 0101 0101 0101 0101

相當於0001 0000 0100 0100 0100 0100 0001 0101。把它移到左邊,你得到0010 0000 1000 1000 1000 1000 0010 1010。我們做0100 0001 0001 0000 0101 0001 0101 0100 | 0010 0000 1000 1000 1000 1000 0010 1010。然後我們得到0110 0001 1001 1000 1101 1001 0111 1110,正如你所看到的,這是解決方案!

+0

爲什麼二進制中的'a'1010?我得到01100001. – Raksha

+2

01100001是一個(字母)轉換爲二進制的_character_代碼,但0xa是十六進制的。 10 = 2 + 0 + 8 + 0,所以它在二進制中表示爲1010。 –

+0

oh%\ ... damm,現在也有十六進制X.x ...以前從未使用過。感謝澄清。 – Raksha

4

轉換爲二進制,

0xaaaaaaaa == 0b10101010101010101010101010101010 
0x55555555 == 0b01010101010101010101010101010101 

這些數字在交替的位置設置0和1,所以當你&與這些中的一個數字,它選擇了每秒位。

如果用一個整數執行swapOddEvenBits程序,比方說0b01111100111101001111110000110010,我們得到

0xaaaaaaaa & 0b01111100111101001111110000110010 selects the following bits: 
       0 1 1 0 1 1 0 0 1 1 1 0 0 1 0 1  # unselected bits are 0 

0x55555555 & 0b01111100111101001111110000110010 selects the following bits: 
       1 1 1 0 1 1 1 0 1 1 1 0 0 1 0 0 

0 1 1 0 1 1 0 0 1 1 1 0 0 1 0 1 gets shifted right: 
0 1 1 0 1 1 0 0 1 1 1 0 0 1 0 1 

and 
1 1 1 0 1 1 1 0 1 1 1 0 0 1 0 0 gets shifted left: 
1 1 1 0 1 1 1 0 1 1 1 0 0 1 0 0 

and we | the results back together: 
0 1 1 0 1 1 0 0 1 1 1 0 0 1 0 1 
1 1 1 0 1 1 1 0 1 1 1 0 0 1 0 0 
------------------------------- 
10111100111110001111110000110001