在C语言中,判断一个整数的二进制表示中1的个数,可以通过以下几种方法实现:
一、位运算方法(推荐)
利用`n & (n - 1)`的特性,每次操作将最右边的1变为0,循环直到n为0,统计次数即为1的个数。此方法效率较高,时间复杂度为O(k),其中k是二进制中1的个数。
示例代码:
```c
include
int countones(unsigned int n) {
int count = 0;
while (n) {
n &= (n - 1);
count++;
}
return count;
}
int main() {
unsigned int num;
printf("请输入一个无符号整数: ");
scanf("%u", &num);
printf("二进制中1的个数为: %dn", countones(num));
return 0;
}
```
二、循环右移法
通过不断将整数右移并与1进行与运算,判断最低位是否为1,直到整数变为0。此方法同样高效,且适用于有符号整数。
示例代码:
```c
include
int countones(int n) {
int count = 0;
while (n) {
count += n & 1;
n >>= 1;
}
return count;
}
int main() {
int num;
printf("请输入一个整数: ");
scanf("%d", &num);
printf("二进制中1的个数为: %dn", countones(num));
return 0;
}
```
三、查表法(适用于固定范围)
对于8位或16位整数,可以预先计算0-255/65535范围内每个数的二进制1的个数,存储在查表数组中,通过查表获取结果。此方法适用于对性能要求较高且数值范围有限的情况。
示例代码:
```c
include
define TABLE_SIZE 256
unsigned char onesTable[TABLE_SIZE] = {0};
void initializeTable() {
for (int i = 0; i < TABLE_SIZE; i++) {
onesTable[i] = (i & 0x55555555) + ((i >> 1) & 0x55555555);
}
}
int countones(unsigned char n) {
return onesTable[n];
}
int main() {
initializeTable();
unsigned char num;
printf("请输入一个8位无符号整数: ");
scanf("%hhu", &num);
printf("二进制中1的个数为: %dn", countones(num));
return 0;
}
```
四、分解法(分治策略)
将整数按每2位一组进行分解,利用`n & 0x3`判断每组是否为`0111`(即4个1),通过位移和加法统计1的个数。此方法适用于中等规模数据。
示例代码:
```c
include
int countones(int n) {
int count = 0;
while (n) {
count += n & 0x3; // 检查最后2位是否为1111
n >>= 2;
}
return count;
}
int main() {
int num;
printf("请输入一个整数: ");
scanf("%d", &num);
printf("二进制中1的个数为: %dn", countones(num));
return 0;
}
```
注意事项
数据类型选择:
无符号整数(如`unsigned int`)能正确处理负数的二进制补码表示,避免符号位影响计数。
效率权衡:
位运算方法(尤其是`n & (n - 1)`)通常比循环或取模操作更高效,推荐优先使用。
扩展性:
若需统计多个数的1的个数,可对上述函数进行修改,通过循环调用或数组批量处理。
通过以上方法,可根据具体需求选择合适的实现方式。