昨天的文章,可能很多人看了不知道怎么回事,确实,我也是看了之后一头雾水。
先给出个简单的例子
#include "stdio.h"int count_bits4(char x)
{x = (x&0x55) + ((x>>1)&0x55);x = (x&0x33) + ((x>>2)&0x33);x = (x&0x0F) + ((x>>4)&0x0F);return x;
}int main()
{printf("%x\n",count_bits4(0x12));
}
输出:
我们现看看下面这段 0x55 = 0b01010101 0x33 = 0b00110011 0x0F = 0b00001111
这个图片需要解释一下 相邻两个数不断相加,直到这个数据的长度
#举个例子
比如我有一个数字,0x34。我要计算0x34里面有多少个1。转成二进制是 0b00110100,这时候,我把它们相邻的二进制位先相加起来。第二步,就是需要把相邻两位的数加起来,第三步,就是把相邻的四位数加起来。
#复杂一点的
#include "stdio.h"int count_bits3(long long s)
{s = (s&0x5555555555555555L) + ((s>>1)&0x5555555555555555L);s = (s&0x3333333333333333L) + ((s>>2)&0x3333333333333333L);s = (s&0x0F0F0F0F0F0F0F0FL) + ((s>>4)&0x0F0F0F0F0F0F0F0FL);s = (s&0x00FF00FF00FF00FFL) + ((s>>8)&0x00FF00FF00FF00FFL);s = (s&0x0000FFFF0000FFFFL) + ((s>>16)&0x0000FFFF0000FFFFL);s = (s&0x00000000FFFFFFFFL) + ((s>>32)&0x00000000FFFFFFFFL);return (int)s;
}
int main()
{printf("%x\n",count_bits3(0x122312351345134));
}
输出:
我们搞清楚了上面的那段代码,再看下面这段代码,是不是觉得没那么吃力了?
#实测大神的代码如何吊打普通代码
test1.c
#include "stdio.h"
#include <time.h>
int count_bits(int x)
{register int xx=x;xx=xx-((xx>>1)&0x55555555);xx=(xx&0x33333333)+((xx>>2)&0x33333333);xx=(xx+(xx>>4))&0x0f0f0f0f;xx=xx+(xx>>8);return (xx+(xx>>16)) & 0xff;
}
int main(void)
{clock_t start, end;start = clock();unsigned int i = 0;for(i = 0;i<10000000;i++){count_bits(12345678);}printf("%d\n",count_bits(12345678));end = clock();double seconds =(double)(end - start)/CLOCKS_PER_SEC;fprintf(stderr, "Use time is: %.8f s\n", seconds);return (0);
}
test2.c
#include "stdio.h"
#include <time.h>
int count_bits2(int x)
{int i = 0;int s = 0;for(i = 0;i<32;i++){if(x&0x01)s ++;x = x>>1;}return (s);
}
int main(void)
{clock_t start, end;start = clock();unsigned int i = 0;for(i = 0;i<10000000;i++){count_bits2(12345678);}printf("%d\n",count_bits2(12345678));end = clock();double seconds =(double)(end - start)/CLOCKS_PER_SEC;fprintf(stderr, "Use time is: %.8f s\n", seconds);return (0);
}
运行:
$ gcc test2.c -o test2
$ gcc test1.c -o test1
$ ./test1
12
Use time is: 0.02542700 s
./test2
12
Use time is: 0.44449600 s
$
#其他方法
在上一篇文章里面,有几个读者说了另外几种方法用来解决这个问题的代码。欣赏一下
代码是程序员的艺术,认真对待代码,让自己变成一个和亚里士多德一样优秀的工程师。
u8 cnt;
while(value)
{value &= value - 1;cnt++;
}
return cnt;
public int NumberOf1(int n) {int count = 0;while (n != 0) {n = n & (n - 1);count += 1;}return count;}
回复「 篮球的大肚子」进入技术群聊
回复「1024」获取1000G学习资料