找到一个数最右边那个1很容易,就是x & -x,那么最左边那个1呢?
【1】移位,逐个check,复杂度O(n),n是bit位数。
【2】先把二进制模式翻转,再求最右边那个1,再翻转回去。复杂度O(lg N)。
【3】得到最右边那个1,然后加到原数字上,这样可以消灭最右边的1,依次这么做,可以找到最左边的1,。这个方法比【1】快。
实现了【2】【3】:
#include<stdio.h>
#include<stdlib.h>
// 1.计算最左边的比特.倒置->最右边比特->倒置
int rev(int x)
{
x = (x & 0xAAAAAAAA)>>1 | (x & 0x55555555)<<1;
x = (x & 0xCCCCCCCC)>>2 | (x & 0x33333333)<<2;
x = (x & 0xF0F0F0F0)>>4 | (x & 0x0F0F0F0F)<<4;
x = (x & 0xFF00FF00)>>8 | (x & 0x00FF00FF)<<8;
x = (x & 0xFFFF0000)>>16 | (x & 0x0000FFFF)<<16;
}
int rb(int x)
{
return x & -x;
}
// 2.迭代消灭最右边比特.
int getl(int x)
{
if(x==0)return 0;
if ((x&(x-1)) == 0)return x; // 注意优先级
while((x&(x-1)) != 0)
{
x += rb(x);
}
return x/2;
}
int main()
{
int i;
for (i=0; i<100; i++)
{
int t = rand()%2000000;
printf("%8x - %8x\t", t, rev(t));
printf("最左边的比特(方法1): %x, \t最左边的比特(方法2): %x\n", rev(rb(rev(t))) , getl(t) );
}
return 0;
}
输出:
46a67 - e6562000
最左边的比特(方法1): 40000,
最左边的比特(方法2): 40000
e3446 - 622c7000
最左边的比特(方法1): 80000,
最左边的比特(方法2): 80000
19d469 - 962b9800
最左边的比特(方法1): 100000,
最左边的比特(方法2): 100000
9b7f3 - cfed9000
最左边的比特(方法1): 80000,
最左边的比特(方法2): 80000
1aab51 - 8ad55800
最左边的比特(方法1): 100000,
最左边的比特(方法2): 100000
3a2ff - ff45c000
最左边的比特(方法1): 20000,
最左边的比特(方法2): 20000
1cc4ca - 53233800
最左边的比特(方法1): 100000,
最左边的比特(方法2): 100000
1adcec - 373b5800
最左边的比特(方法1): 100000,
最左边的比特(方法2): 100000
7e229 - 9447e000
最左边的比特(方法1): 40000,
最左边的比特(方法2): 40000
190bcd - b3d09800
最左边的比特(方法1): 100000,
最左边的比特(方法2): 100000
1258ba - 5d1a4800
最左边的比特(方法1): 100000,
最左边的比特(方法2): 100000
77a2b - d45ee000
最左边的比特(方法1): 40000,
最左边的比特(方法2): 40000
14e272 - 4e472800
最左边的比特(方法1): 100000,
最左边的比特(方法2): 100000
7ef7b - def7e000
最左边的比特(方法1): 40000,
最左边的比特(方法2): 40000
db2e3 - c74db000
最左边的比特(方法1): 80000,
最左边的比特(方法2): 80000
1719c6 - 6398e800
最左边的比特(方法1): 100000,
最左边的比特(方法2): 100000
12037c - 3ec04800
最左边的比特(方法1): 100000,
最左边的比特(方法2): 100000
5d9c2 - 439ba000
最左边的比特(方法1): 40000,
最左边的比特(方法2): 40000
15c54 - 2a3a8000
最左边的比特(方法1): 10000,
最左边的比特(方法2): 10000
163678 - 1e6c6800
最左边的比特(方法1): 100000,
最左边的比特(方法2): 100000
f569b - d96af000
最左边的比特(方法1): 80000,
最左边的比特(方法2): 80000
。。。 多的就不贴了。