📅  最后修改于: 2023-12-03 14:39:37.893000             🧑  作者: Mango
在编程中,我们常常需要计算某个整数中设置的位数,也就是二进制表示中为1的位数。本文介绍如何使用C/C++编写一个高效的程序来实现这个功能。
最简单、也是最容易想到的方法是遍历整数的所有二进制位,并统计为1的位数。具体方法如下:
int count_bits(unsigned int n) {
int count = 0;
while (n > 0) {
if (n & 1) { // 如果最低位为1
count ++;
}
n >>= 1; // 逐位右移
}
return count;
}
这种方法的时间复杂度为O(log n),其中n是整数的位数。虽然时间复杂度较低,但在实际应用中可能不够快。
由于一个8位二进制数中最多只有8个为1,所以可以预先计算0到255中所有数字的二进制表示中为1的位数,并保存在一个256个元素的数组(即查找表)中。在计算一个较大的整数中为1的位数时,可以将它分成几个较小的部分,每个部分最多只有8位,然后在查找表中查找每个部分中为1的位数,并将它们相加即可。具体方法如下:
int count_bits(unsigned int n) {
// 查找表,表中第i项存储i的二进制表示中为1的位数
static const int table[] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 6, 7, 7, 8, 7, 8, 8, 9
};
int count = 0;
// 分四个字节进行计算,每个字节都在查找表中查找
// 每个字节对应一个查找表中的元素,将四个结果相加即可
count += table[n & 0xff];
count += table[(n >> 8) & 0xff];
count += table[(n >> 16) & 0xff];
count += table[n >> 24];
return count;
}
这种方法的时间复杂度为O(1),但需要较大的空间来存储查找表。在计算较小的整数时,这种方法可能比暴力法更慢。
这种方法是用一些巧妙的位运算技巧来计算一个整数中为1的位数,其时间复杂度为O(log n),运行速度比较快。具体方法如下:
int count_bits(unsigned int n) {
int count = 0;
while (n > 0) {
n &= (n - 1); // 将n的最低位1变为0
count ++;
}
return count;
}
这种方法的基本思想是,从右往左枚举n的二进制位,每次将n的最低位1变为0,并统计次数。这个操作可以用一个简单的位运算实现:n &= (n - 1)。这个操作会抹掉n的最低位1,因此将n的最低位1变为0的次数就是n中为1的位数。
本文介绍了三种计算整数中为1的位数的方法,即暴力法、查表法和位运算法。这些方法各有优缺点,可以根据实际需求选择合适的方法。