📌  相关文章
📜  C C++程序对整数中的设置位进行计数(1)

📅  最后修改于: 2023-12-03 14:39:37.893000             🧑  作者: Mango

C/C++程序对整数中的设置位进行计数

在编程中,我们常常需要计算某个整数中设置的位数,也就是二进制表示中为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的位数的方法,即暴力法、查表法和位运算法。这些方法各有优缺点,可以根据实际需求选择合适的方法。