int main()
{
int x = 1000, count = 0;
for (int i = 0; i < 32; i++)
{
if (x & 0x01)
{
count++;
}
x = x >> 1;
}
printf("%d
", count);
return 0;
}
第一种最简单,只要让这个数字跟 0x01 进行与运算,就能判断出来最低位是不是1。然后右移一位,进行同样的操作。循环32次,就能得到结果。这是刚入门C语言的同学写的代码。
int main()
{
int x = 1000, count = 0;
while (x)
{
x = x & (x - 1);
count++;
}
printf("%d
", count);
return 0;
}
第二种稍微厉害一些,用到了 x & (x - 1) 这么一行代码,它的作用就是让二进制表示中最后一个 1 变成 0 ,不断的让这些 1 变成 0,最后这个数字也就变成了 0 ,只要知道这行代码执行了多少次,结果也就知道了。能写出这个代码,简历上写个掌握C语言编程一点也不为过。
int main()
{
unsigned int temp = 1000;
temp = (temp & 0x55555555) + ((temp & 0xaaaaaaaa)>>1);
temp = (temp & 0x33333333) + ((temp & 0xcccccccc)>>2);
temp = (temp & 0x0f0f0f0f) + ((temp & 0xf0f0f0f0)>>4);
temp = (temp & 0xff00ff) + ((temp & 0xff00ff00)>>8);
temp = (temp & 0xffff) + ((temp & 0xffff0000)>>16);
printf("%d
", temp);
return 0;
}
最后一种比较炸裂,本来很简单的一个问题,被它写得非常复杂。这是当年阿里的一道C语言笔试题。代码的功能也是计算整数 temp 的二进制表示中 1 的个数。原题中 temp 的值是 0x11530828,换成二进制是:
0001 0001 1001 0011 0000 1000 0010 1000
假设有个二进制数:01,含有 1 个 1,正好二进制 01 对应的十进制也是 1。再假设有个二进制数 11,含有 2 个 1,正好二进制 11 对应的十进制是 2。于是不难得出一个结论:如果一个二进制数只有两位,那么它对应的十进制数就是该二进制中包含的 1 的个数。算法中核心的代码有 5 行,分别是:
temp = (temp & 0x55555555) + ((temp & 0xaaaaaaaa)>>1);
temp = (temp & 0x33333333) + ((temp & 0xcccccccc)>>2);
temp = (temp & 0x0f0f0f0f) + ((temp & 0xf0f0f0f0)>>4);
temp = (temp & 0xff00ff) + ((temp & 0xff00ff00)>>8);
temp = (temp & 0xffff) + ((temp & 0xffff0000)>>16);
每一行的作用都是让相邻的两位相加,temp的原始值是:
0001 0001 1001 0011 0000 1000 0010 1000
经过第一行代码,相邻的两个数字相加,得到:
0 1 0 1 1 1 0 2 0 0 1 0 0 1 1 0
对应的 temp 是:
0000 0100 0001 010
经过第二行代码,相邻的两个数字相加,得到:
1 1 2 2 0 1 1 1
对应的 temp 是:
0001 0001 0010 0010 0000 0001 0001 0001
经过第三行代码,相邻的两个数字相加,得到:
2 4 1 2
对应的 temp 是:
0000 0001 0000 0010
经过第四行代码,相邻的两个数字相加,得到:
6 3
对应的 temp 是:
0000 0000 0000 0110 0000 0000 0000 0011
经过第五行代码,相邻的两个数字相加,得到:
9
对应的 temp 是:
0000 0000 0000 0000 0000 0000 0000 1001
结果就是整数 temp 二进制表示中 1 的个数。
全部0条评论
快来发表一下你的评论吧 !