计算unsigned int型数据二进制形式中1出现的次数

int GetCount(unsigned int num)
{
	/*在这里实现功能*/
	unsigned int cnt = 0;

	while(num)
	{
		cnt += num&0x01;
			num >>= 1;
	}
	return cnt++;
}

在C/C++中,计算 `unsigned int` 的二进制中 `1` 的个数(也称为 **Population Count** 或 **Popcount**)有以下几种高效方法: --- ### **方法1:逐位检查(基础方法)** ```c unsigned int count_ones(unsigned int num) { unsigned int count = 0; while (num) { count += num & 1; // 检查最低位 num >>= 1; // 右移一位 } return count; } ``` - **时间复杂度**:`O(log₂ num)`,即与位数相关。 - **缺点**:对于高位全是 `0` 的数仍有不必要的循环。 --- ### **方法2:Brian Kernighan 算法(优化版逐位清除)** ```c unsigned int count_ones(unsigned int num) { unsigned int count = 0; while (num) { num &= (num - 1); // 清除最低位的 1 count++; } return count; } ``` - **原理**:`num & (num - 1)` 会直接清除最低位的 `1`(例如 `0b1010 & 0b1001 = 0b1000`)。 - **时间复杂度**:`O(k)`,其中 `k` 是 `1` 的个数,比方法1更高效。 --- ### **方法3:查表法(空间换时间)** ```c // 预计算 8 位数的 1 的个数(256 种可能) const unsigned char table[256] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, // ... 剩余 240 个值(可通过程序生成) }; unsigned int count_ones(unsigned int num) { return table[num & 0xFF] + table[(num >> 8) & 0xFF] + table[(num >> 16) & 0xFF] + table[(num >> 24) & 0xFF]; } ``` - **优点**:`O(1)` 时间复杂度,适合大量调用。 - **缺点**:需要额外的存储空间(256 字节)。 --- ### **方法4:编译器内置函数(最优解)** 现代编译器(如 GCC、Clang)提供内置函数: ```c unsigned int count_ones(unsigned int num) { return __builtin_popcount(num); // GCC/Clang 专用 } ``` 或 C++20 标准库: ```cpp #include <bit> unsigned int count_ones(unsigned int num) { return std::popcount(num); // C++20 标准支持 } ``` - **原理**:编译器会生成最优化的机器指令(如 x86 的 `POPCNT`)。 - **性能**:单条 CPU 指令完成,是最快的方法。 --- ### **方法5:位运算技巧(分治法)** ```c unsigned int count_ones(unsigned int num) { num = (num & 0x55555555) + ((num >> 1) & 0x55555555); num = (num & 0x33333333) + ((num >> 2) & 0x33333333); num = (num & 0x0F0F0F0F) + ((num >> 4) & 0x0F0F0F0F); num = (num & 0x00FF00FF) + ((num >> 8) & 0x00FF00FF); num = (num & 0x0000FFFF) + ((num >> 16) & 0x0000FFFF); return num; } ``` - **原理**:通过分治策略,逐级合并相邻位的 `1` 的个数。 - **优点**:无分支、无查表,适合某些嵌入式场景。 --- ### **性能对比** | 方法 | 时间复杂度 | 适用场景 | |--------------------|------------|-----------------------------| | 逐位检查 | O(log₂ n) | 简单但慢 | | Brian Kernighan | O(k) | 常规优化 | | 查表法 | O(1) | 频繁调用,允许额外空间 | | 编译器内置/标准库 | O(1) | 最高效,优先使用 | | 位运算分治 | O(1) | 无硬件支持时的替代方案 | --- ### **代码示例(完整)** ```c #include <stdio.h> int main() { unsigned int num = 0b11011010; // 218 (二进制 11011010) printf("1 的个数: %u\n", count_ones(num)); return 0; } ``` **输出**: ``` 1 的个数: 5 ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值