统计一个数二进制形式中1的个数

题目要求

写一个参数二进制中1的个数,比如:

15----> 0000 1111 ----> 4个1


函数原型

int count_one_bits(unsigned int value)
{
     //返回1的个数
}

【实现代码及思路】

思路一:我们知道,一个无符号整数在内存中占用了4个字节即32个bit位,既然是想统计二进制中1 的个数,我们就可以遍历这32个bit位,每遇到一个1,计数器就++,之后返回计数器的位数即可。

注意:本题中要用到某些操作符,具体使用可参考:操作符的秘密

实现代码:

//统计二进制中1的个数
	int count_one_bits(unsigned int value)
{
	int i = 0;
	int count = 0;
	for (i = 0; i < 32; ++i)
	{
		if (((value>>i) & 1) == 1)
		{
			++count;
		}
	}
	return count;
}


思路2:通过对一个数不断模除统计二进制中1的个数,如果该数据%2等于1就对计数器进行加加,然后对其进行除2,重复以上步骤,直到该数据等于0退出,返回计数器。例如:

(原数据)15---->0000 1111---->4个1

(15 / 2)    7---->0000 0111---->3个1

(7  / 2)      3---->0000 0011---->2个1

(3  / 2)      1---->0000 0001---->1个1

(1  / 2)      0---->0000 0000---->0个1


(原数据)20---->0001 0100---->2个1

(20 / 2)  10---->0000 1010---->2个1

(10 / 2)    5---->0000 0101---->2个1

(5  / 2)      2---->0000 0010---->1个1

(2  / 2)      1---->0000 0001---->1个1

(1  / 2)     0---->0000 0000---->0个1 

实现代码:

int count_one_bits2(unsigned int value)
{
	int count = 0;
	while(value)
	{
		if (value%2 == 1)//说明value是奇数
		{
			++count;
		}
		value >>= 1;//在二进制中右移一位就相当于除2,除2就可去掉最高位的1
	}
	return count;
}


注意: 此种算法只能能对无符号的整数进行统计,如果是负数,则会导致死循环或是计算结果不准确。例如:

int value = -1;

因为-1%2=-1、-1/2=0、-1>>1=-1,所以用此算法对负数进行统计是不适用的。

【测试负数计算错误】

int count_one_bits2(int value)
{
	int count = 0;
	while(value)
	{
		if (value%2 == 1)
		{
			++count;
		}
		value /= 2;
	}
	return count;
}

【测试负数导致死循环】

int count_one_bits2(int value)
{
	int count = 0;
	while(value)
	{
		if (value%2 == 1)
		{
			++count;
		}
		value >>= 1;
	}
	return count;
}

思路3:假设要统计初始值是n,我们可通过n=n&(n-1)来去掉最高位的1,进行统计,知道n==0结束,返回计数器。

例如:计数器count初始值为0,原数据为15

++count = 1---->15&14---->0000 1111&0000 1110---->0000 1110(14)

++count = 2---->14&13---->0000 1110&0000 1101---->0000 1100(12)

++count = 3---->12&11---->0000 1100&0000 1011---->0000 1000(8)

++count = 4---->8  &  7---->0000 1000&0000 0111---->0000 0000(0)

代码实现:

int count_one_bits3(unsigned int value)
{
	int count = 0;
	while(value)
	{
		count++;
		value = value&(value-1);
	}
	return count;
}

完整代码:

#include <stdio.h>
#include <stdlib.h>
//统计二进制中1的个数
	int count_one_bits1(unsigned int value)
{
	int i = 0;
	int count = 0;
	for (i = 0; i < 32; ++i)
	{
		if (((value>>i) & 1) == 1)
		{
			++count;
		}
	}
	return count;
}
int count_one_bits2(unsigned int value)
{
	int count = 0;
	while(value)
	{
		if (value%2 == 1)
		{
			++count;
		}
		value >>= 1;
	}
	return count;
}
int count_one_bits3(unsigned int value)
{
	int count = 0;
	while(value)
	{
		count++;
		value = value&(value-1);
	}
	return count;
}
int main()
{
	printf("%d ",count_one_bits1(-1));
	printf("%d ",count_one_bits1(0));
	printf("%d\n",count_one_bits1(15));

	printf("%d ",count_one_bits2(0));
	printf("%d ",count_one_bits2(15));
	printf("%d\n",count_one_bits2(20));

	printf("%d ",count_one_bits3(-1));
	printf("%d ",count_one_bits3(0));
	printf("%d\n",count_one_bits3(15));
	system("pause");
	return 0;
}

运行结果:


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值