ORBSLAM2计算描述子距离——C++ 位操作得到二进制32位int值中有多少个1

看ORBSLAM2时算描述子之间的距离时看到的神奇的位操作,特此记录一哈。

    unsigned  int v = *pa ^ *pb;   
    v = v - ((v >> 1) & 0x55555555);
    v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
    dist += (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;

pa和pb分别是两个描述子,进行异或操作得到一个32位int值,里面包含多个1,1的个数和即为两个描述子之间的距离。
然后通过三个语句12个操作即可得到1的个数。

大概说一下我自己的解释,比较蠢吧,仅供参考。

0x55555555=01010101 01010101 01010101 01010101
我们把32位分成16个2位来看,即XX(X未知,可0可1),我们会发现int a=XX-(XX>>1)&01的结果即为XX中1的数量。

XX>>1=0X

然后会发现int a=XX-(XX>>1)&01后得到的int值即为XX中1的个数。即XX=00时,a=0,XX=01时,a=1,XX=10时,a=1,XX=11时,a=2。

那么同理,v=v-((v>>1)&0x55555555)得到了32位int值v,将此时的v每两位表示的int值相加即为原v中1的个数。

接下来

v = (v & 0x33333333) + ((v >> 2) & 0x33333333);

0x33333333=00110011 00110011 00110011 00110011

很明显,这一步操作是v拆成8个4位,每个4位代表的int值之和即为原v中1的个数,每个4位是由上式中的结果v的相邻2位拼接得到的。

同理可得v + (v >> 4)) & 0xF0F0F0F是把之前的相邻4位拼接成8位,则此时32位int值四个八位代表的int值之和即为1的个数。

之后乘0x1010101的目的是把每个8位的数加到25-32位上,然后右移24位移到末8位,即可得到四个八位的int值之和,即1的个数。

你可能感兴趣的:(C++)