统计整数二进制表示中1的个数

本文介绍几种高效计算二进制数中1的数量的方法,包括直接逐位检查、使用位运算优化以及采用分治策略进行进一步优化。

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

解决这个问题第一想法肯定是一位一位的去判断,是1计数器+1,否则不操作,跳到下一位,十分容易,编程初学者就可以做得到!

 

于是很容易得到这样的程序:

 

int Sum1ByBin(int num)
{
	int sum = 0;
	while (num)
	{
		if(sum %2 ==1)
		{
			sum ++;
		}
		sum/=2;
	}
	return sum;
}


 

 


或者用牛逼的位运算:

 

int Sum1ByBin(int num)
{
	int sum = 0;
	while (num)
	{
		sum += num&1;
		num>>1;
	}
	return sum;
}

 

 

上面这两篇代码是用的同样的算法, 时间复杂度是二进制的位数,于是可以想一下,有没有只有与二进制中1的位数相关的算法呢?

可以考虑每次找到从最低位开始遇到的第一个1,计数器加1然后把它清零,然后继续找下一个1。方法就是n&(n-1),这个操作对比当前位高的位没有任何影响,

对低位完全清零。举个栗子吧!5。 5是101,第一次运算101&100 == 100,并且计数器加一,第二次运算100&011 == 0,计数器加一。循环结束啦!

所以5有2个1。牛逼吧! 看看代码是怎么实现的:

 

int Sum1byBin(int num)
{
	int sum = 0;
	while(num)
	{
		num &= num-1;
		sum++;
	}
	return 0;
}

很是简单,这就是位运算的好处,据说这个算法没把位运算发挥到极致,也没有得到这个算法最优解。

 

请读者先look一段代码,看看能不能看懂是什么功能:

 

int Sum1byBin(int num)
{
	num =	(num&0x55555555)	+	((num>>1)&0x55555555);
	num = (num&0x33333333)	+	((num>>2)&0x33333333);
	num	=	(num&0x0f0f0f0f)	+	((num>>4)&&0x0f0f0f0f);
	num	=	(num&0x00ff00ff)	+	((num>>4)&&0x00ff00ff);
	num	=	(num&0x0000ffff)	+	((num>>4)&&0x0000ffff);

	return num;
}

卧槽,这个是在玩什么中的制表符导致空格这么大的不怪我!

 

回想第一次遇到这个代码的时候我第一印象,这是什么**玩意,后来经过分析并且有高手帮助理解,这个功能正是利用了位运算,将一个数中二进制表中1 的个数算了出来。利用的是分治思想,先计算每对相邻的2位中有几个1,再计算相邻的4位有一个1 ,再计算相邻的8位、16位、32位有几个1,到此结束,32位的机器int就是32位,所以算

到32位就够啦!!!

 

 

 

转载于:https://my.oschina.net/u/2822116/blog/790382

### 计算整数二进制表示1的数量 对于计算整数在其二进制形式中有多少个`1`,存在多种方法可以实现这一目标。下面介绍几种常见的算法。 #### 取余法 通过不断对给定数值除以2并检查其余数是否为1统计二进制位上的1的数目。这种方法简单直观但效率较低,因为每次迭代都需要执行一次除法操作[^4]。 ```python def count_binary_ones_remainder(num): count = 0 while num != 0: remainder = num % 2 if remainder == 1: count += 1 num //= 2 return count ``` #### 移位法 利用按位右移运算符逐步处理每一位直到所有的比特都被访问过为止。此方式同样适用于正负整数,在某些情况下可能比取模更高效一些[^3]。 ```c++ #include <iostream> using namespace std; int main() { int value; cin >> value; unsigned int uValue = static_cast<unsigned int>(value); int count = 0; for (unsigned int i = 0; i < sizeof(int)*8 ; ++i){ if((uValue>>i)&1) count++; } cout << "count=" << count << endl; } ``` #### 高级计算法——Brian Kernighan’s Algorithm 这是一种更为高效的解决方案,它基于这样一个事实:当我们将一个数字与其减去一的结果做按位与(&&)时会清除掉最右边的那个'1'。因此只要这个过程不返回零就可以持续减少原值直至其变为零,并在此过程中计数被清除了几次即可得到最终结果[^5]。 ```cpp // C++ implementation of Brian Kernighan's algorithm to find the number of set bits in an integer. int countSetBits(unsigned int n) { int count = 0; while(n){ n &= (n-1); // Clearing the least significant bit set count++; } return count; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值