写一个函数返回参数二进制中 1 的个数

本文介绍了三种方法来计算一个数的二进制表示中1的个数,包括模2除2的方法、按位与判断以及使用n&(n-1)的优化解。并分别以11和-11为例,详细解释了每种方法的逻辑和运算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写一个函数返回参数二进制中1的个数。
方法1:采用模2除2的方法
在这里我们以11为例子

11在内存中的存储是二进制:0000 0000 0000 0000 0000 0000 0000 1011
11%2=1
再将11/2(也可以看成二进制数右移一位)

11/2=5 其二进制:0000 0000 0000 0000 0000 0000 0000 0101
5%2=1

此时再将 5/2(再进行了一次右移动)
得到2 其二进制: 0000 0000 0000 0000 0000 0000 0000 0010
2%2=0

再将2/2(又进行了一次右移动)
得到1 其二进制:0000 0000 0000 0000 0000 0000 0000 0001
1%2=1

再将1/2 得到0 二进制:0000 0000 0000 0000 0000 0000 0000 0000
二进制中再无1,结束判断

可知11的二进制中1的个数有3个
代码如下:

int count_one_bits(unsigned int value){
	int count = 0;//用来存储1的个数
	while (value > 0){
		if (value % 2 == 1){
			++count;
			value = value / 2;
		}
		else{
			value = value / 2;
		}
	}
	return count;
}
int main(){
	int a = 11;
	printf("%d\n", count_one_bits(a));
	system("pause");
	return 0;
}

在这里插入图片描述
看到这里,就有小伙伴会很好奇了,负数的二进制又有几个1呢
这里就要提及负数在内存中的存储啦,负数在内存中是以补码的形式存储
以-11为例子
-11: //原码: 1000 0000 0000 0000 0000 0000 0000 1011
//反码: 1111 1111 1111 1111 1111 1111 1111 0100
//补码: 1111 1111 1111 1111 1111 1111 1111 0101
补码为反码+1,要注意的是在这个过程中,最高位为符号位,是不用变化的。

方法2:利用按位与判断,与1按位与,最低位为0,代表原数的最低位为0;最低位为1,代表原数的最低位为1
代码如下

int count_one_bits2(int unsigned value){
	int count = 0;
	for (int i = 0; i < 32; i++){
		//利用按位与判断,与1按位与,最低位为0,代表原数的最低位为0;最低位为1,代表原数的最低位为1
		if ((value&1) == 1){
			count++;
		}
		value = value >> 1;//等价于value/=2
	}
	return count;
}

这里面需要注意的是,运算符的优先级,因为==的运算优先级大于&

方案3(较优解)n&(n-1)
以11 为例子
//11 :0000 0000 0000 0000 0000 0000 0000 1011
//10: 0000 0000 0000 0000 0000 0000 0000 1010
11&10:0000 0000 0000 0000 0000 0000 0000 1010 //10
//9: 0000 0000 0000 0000 0000 0000 0000 1001 //9
10&9: 0000 0000 0000 0000 0000 0000 0000 1000 //8
//7 :0000 0000 0000 0000 0000 0000 0000 0111
8&7: 0000 0000 0000 0000 0000 0000 0000 0000
进行三次的n&(n-1),即为11二进制中1的个数
代码如下

int count_one_bits3(int unsigned value){
	int count = 0;
	while (value > 0){
		 value=value&(value - 1);
		 ++count;
	}
	return count;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值