求二进制数中1的个数

求整数的二进制表示中1的个数,最直接的方式是求出其二进制表示,再计算出二进制表示中1的个数。但是这种方法的效率较低。因为我们只需要统计二进制表示中1的个数,所以没有必要将整数先转化为二进制,可以在对整数处理的过程中计数。整数转化为二进制,除了直接除以2以外,位操作的右移一位可以实现同样的功能。右移过程中会将最后一们直接丢弃,因此在右移操作之前需要先判断最后一们是否为1,使用“与”操作可以实现。例如如果n的最后一样是1,那么a & 0x01 = 1,否则a & 0x01 = 0。由此可以写出实现代码:

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     int n, s = 0;
 6     scanf("%d", &n);
 7     while(n)
 8     {
 9         s += n & 0x01; //判断最后一位是否为1
10         n >> 1;   // 移位操作
11     }
12     printf("%d\n", s);
13     return 0;
14 }

对于上述程序还存在可以改进的地方:操作过程中只考虑二进制表示中的“1”。具体实现如下:

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     int n, s = 0;
 6     scanf("%d", &n);
 7     while(n)
 8     {
 9         n &= (n - 1);
10         s++;
11     }
12     printf("%d\n", s);
13     return 0;
14 }

 

然后回复中的这些代码不懂

 1 你可以试试这几种算法,会比你的快n倍。
 2 
 3 #if 0
 4 x = (x & 0x55555555) + ((x >> 1) & 0x55555555); 
 5 x = (x & 0x33333333) + ((x >> 2) & 0x33333333); 
 6 x = (x & 0x0f0f0f0f) + ((x >> 4) & 0x0f0f0f0f); 
 7 x = (x & 0x00ff00ff) + ((x >> 8) & 0x00ff00ff); 
 8 x = (x & 0x0000ffff) + ((x >> 16) & 0x0000ffff); 
 9 #elif 0
10 // mit hackmem count
11 x = x - ((x >> 1) & 0x55555555);
12 x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
13 x = (x + (x >> 4)) & 0x0f0f0f0f;
14 x = x + (x >> 8);
15 x = x + (x >> 16);
16 x &= 0x7f;
17 #elif 0
18 x = x - ((x >> 1) & 0x55555555);
19 x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
20 x = (x + (x >> 4) & 0x0f0f0f0f);
21 x = (x * 0x01010101) >> 24;
22 #elif 0
23 x = x - ((x >> 1) & 0x55555555);
24 x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
25 x = (x + (x >> 4) & 0x0f0f0f0f) % 255;
26 #elif 0 // faster
27 x = x - ((x >> 1) & 0x77777777) - ((x >> 2) & 0x33333333) - ((x >> 3) & 0x11111111);
28 x = (x + (x >> 4) & 0x0f0f0f0f);
29 x = (x * 0x01010101) >> 24;
30 #else
31 x = __builtin_popcount(x); // for gcc
32 #endif

转自:

http://blog.csdn.net/furney/article/details/7479925

posted @ 2012-04-24 10:24  ziyoudefeng  阅读(391)  评论(0编辑  收藏  举报