Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 构造一个逻辑表达式,它将对字节中的位进行计数_C_Bitwise Operators - Fatal编程技术网

C 构造一个逻辑表达式,它将对字节中的位进行计数

C 构造一个逻辑表达式,它将对字节中的位进行计数,c,bitwise-operators,C,Bitwise Operators,在面试新候选人时,我们通常要求他们编写一段C代码,以计算给定字节变量中值为1的位数(例如,字节3有两个1位)。我知道所有常见的答案,比如右移8次,或者索引256个预计算结果的常量表 但是,有没有更聪明的方法不使用预计算表?计算1位数的字节操作(AND、OR、XOR、+、-、二进制求反、左移位和右移位)的最短组合是什么?至少有两种更快的解决方案,具有不同的性能特征: 减去一,然后将新值和旧值相加。重复到零。计算迭代次数。复杂度:O(B),其中B是一位的数量 int bits(unsigned n)

在面试新候选人时,我们通常要求他们编写一段C代码,以计算给定字节变量中值为1的位数(例如,字节3有两个1位)。我知道所有常见的答案,比如右移8次,或者索引256个预计算结果的常量表


但是,有没有更聪明的方法不使用预计算表?计算1位数的字节操作(AND、OR、XOR、+、-、二进制求反、左移位和右移位)的最短组合是什么?

至少有两种更快的解决方案,具有不同的性能特征:

  • 减去一,然后将新值和旧值相加。重复到零。计算迭代次数。复杂度:O(B),其中B是一位的数量

    int bits(unsigned n)
    {
        for (int i = 0; n; ++i)
        {
            n &= n - 1;
        }
        return i;
    }
    
  • 先加成对的位,再加四组,再加八组,直到达到字长。有一个技巧可以让你在一个关卡中添加每个级别的所有组。复杂度:O(log(N)),其中N是位的总数

    int bits(uint32 n)
    {
        n = (n & 0x55555555) + ((n >>  1) & 0x55555555);
        n = (n & 0x33333333) + ((n >>  2) & 0x33333333);
        n = (n & 0x0f0f0f0f) + ((n >>  4) & 0x0f0f0f0f);
        n = (n & 0x00ff00ff) + ((n >>  8) & 0x00ff00ff);
        n = (n & 0x0000ffff) + (n >> 16);
        return n;
    }
    
    这个版本有点幼稚。如果你想一想,你可以避免一些操作

  • 下面列出了Java这样做的方法(使用32位整数)(14次计算)

    对于16位整数(简称),该方法可以重写为:

    private static int bitCount(int i) {
       // HD, Figure 5-2
       i = i - ((i >>> 1) & 0x5555);
       i = (i & 0x3333) + ((i >>> 2) & 0x3333);
       i = (i + (i >>> 4)) & 0x0f0f;
       i = i + (i >>> 4);
       i = i + (i >>> 8);
       return i & 0x3f;
    }
    
    对于8位整数(字节),它有点复杂,但总体思路是这样的

    有关快速位计数功能的更多信息,请查看此链接:

    对于任何整数,最快/最简单的方法是:对于最佳情况,为O(0),对于最坏情况,为O(n)(其中n是值中的位数)


    我认为第一个应该返回I而不是n。关于最后一个:理论上和实践上,最好的情况仍然是O(1)。还值得注意的是,如果您使用典型的大整数表示(例如BigInteger而不是int),那么最坏的情况通常是O(n^2)。的可能重复
    private static int bitCount(int i) {
       // HD, Figure 5-2
       i = i - ((i >>> 1) & 0x5555);
       i = (i & 0x3333) + ((i >>> 2) & 0x3333);
       i = (i + (i >>> 4)) & 0x0f0f;
       i = i + (i >>> 4);
       i = i + (i >>> 8);
       return i & 0x3f;
    }
    
    static private int bitcount(int n)  {
       int count = 0 ;
       while (n != 0)  {
          count++ ;
          n &= (n - 1) ;
       }
       return count ;
    }