2017-05-11 1008 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 
相关问题