C语言——求一个数字的二进制中 1 的个数

写一个程序打印指定数字的二进制中 1 的个数,比如:15 (0000 1111)   输出4

下面是三种方式:

①通过模2除2(%2、/2)的方法

num%2——取出二进制的最后一位

num/2——右移去掉二进制的最后一位

通过while循环,依次取出二进制的最后一位数字判断是否为1,若为1则count++,while(num)只有当num变为0时循环结束。

问题:在测试-1出现bug,-1的二进制中应该有32个1,输出却为0。我们将-1带入代码中发现-1%2=0,count不增,然后-1/2=0,循环结束,故输出count的值为0。

解决方案:将变量num的数据类型改为unsigned int (无符号整型),此时表示的是正的整型的最大值,所以当num=-1时,表示二进制为32个1的正数,通过循环可以输出正确的个数。

代码1:

#include <stdio.h>

int main()
{
	int num = 15;
      //unsigned int num = -1;
      //改为无符号整型消除bug,表示正的整型的最大值
        int count = 0;//计数
	while (num)
	{
		if (num % 2 == 1)
			count++;
		num = num / 2;
	}
	printf("二进制中1的个数为:%d\n",count);
	return 0;
}
②通过右移操作符(>>)、按位与操作符(&)实现

Example:当num=10(1010),通过右移操作num>>i,二进制向右移动i位。

//i=0,num>>0,右移0位,此时(1010)&(0001)=0

//i=1,num>>1,右移1位,此时(0101)&(0001)=1,count++

//i=2,num>>2,右移2位,此时(0010)&(0001)=0

//i=3,num>>3,右移3位,此时(0001)&(0001)=1,count++

……

因为二进制共32位,所以循环要执行32次后结束,得到count为2。

缺点:不够高效,必须循环32次

代码2(优化1):

#include <stdio.h>

int count_one_bits(unsigned int value)
{
	int count = 0;
	int i = 0;
	for (i = 0; i < 32; i++)
	{
		if ((value>>i)&1 == 1)
			count++;
	}
	return count; // 返回1的位数 
}
int main()
{
	int number = 0;
	printf("Input:");
	scanf("%d",&number);
	printf("%d\n",count_one_bits(number));
	return 0;
}
③通过按位与操作符(&)巧妙运算实现

Example:  当num=15时,

1//num&(num-1)=(1111)&(1110)=(1110)   

2//num&(num-1)=(1110)&(1101)=(1100)  

3//num&(num-1)=(1100)&(1011)=(1000)  

4//num&(num-1)=(1000)&(0111)=0  ,循环停止。共执行4次while循环。

可以发现:每执行一次就去掉了最右边的1,so~循环执行几次就有几个1啦~

高效!有几个1就处理几次

代码3(优化2):

#include <stdio.h>

int main()
{
	int num = 15;
	int count = 0;
	int i = 0;
	while (num)
	{
          num = num&(num - 1);
          count++;
 	}
	printf("二进制中1的个数为:%d\n",count);
	return 0;
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值