了解位逆转的给定代码段

时间:2018-04-22 05:19:05

标签: c++

我在程序员提交的'codefights'上找到了这个片段。我对这个问题的解决方案是30行,而这只是一种美。 但我无法理解逻辑。 任何人都可以解释这一点。

int mirrorBits(int a) {
 int r = 0;

 for (; a; a >>= 1) 
    r = r << 1 | a & 1;  
 return r;
}

输入a = 8;输出:1

1 个答案:

答案 0 :(得分:3)

首先,这里有一个非常好的StackOverflow答案: Most Efficient Algorithm for Bit Reversal ( from MSB->LSB to LSB->MSB) in C

该算法使用

>> ... binary shift right (100b >> 1 == 10b)
<< ... binary shift left (100b << 1 == 1000b
| .... binary or (100b | 10b == 110b)
& .... binary and (111b & 100b == 100b)

for循环将a向右移动,直到所有位都退出a。

想象一下,你从a = 101101开始,然后&gt;&gt; = 1执行以下操作:

At the end of loop 1:  a == 10110
At the end of loop 2:  a == 01011
At the end of loop 3:  a == 00101
At the end of loop 4:  a == 00010
At the end of loop 5:  a == 00001
At the end of loop 6:  a == 00000 (condition fails -> loop ends)

循环体向右移动b,使用&amp;掩盖a的最后一位并将其作为最后一位添加到b。或者可以用来添加最后一位数,因为&lt;&lt;为所有“新”位插入0。

想象一下你以a = 101101

开头
  • 循环1:a = 10110 1 ,r = 0 =&gt; 0 <强> 1
  • 循环2:a = 01011 0 ,r = 01 =&gt; 01的 0
  • 循环3:a = 00101 1 ,r = 010 =&gt; 010的 1
  • 循环4:a = 00010 1 ,r = 0101 =&gt; 0101的 1
  • 循环5:a = 00001 0 ,r = 01011 =&gt; 01011的 0
  • 循环6:a = 00000 1 ,r = 010110 =&gt; 010110的 1

详细内部循环#3执行以下操作: (a是001011,r是010)

r&lt;&lt; 1将r从010更改为0100.最后一位是插入的0。 a&amp; 1屏蔽当前的最后一位(00101中的1 1 ) 现在我们有(0100 | 1),其结果是0101。

警告:此算法并未实际镜像这些位,因为如果将算法应用于结果,则不会获得原始值。

如果需要镜像32位无符号整数,则必须独立于a的值循环32次:

unsigned int r = 0;
unsigned int a = 12345;

for(int i = 0; i < 32; ++i)
{
   r = (r << 1) | (a & 1);
   a >>= 1;
}

如果您应用此算法两次,则应获得原始值。