【问题标题】:count number of set bits in integer以整数计数设置的位数
【发布时间】:2023-03-14 05:17:01
【问题描述】:

我正在研究关于位计数的不同方法,或者给定整数的人口计数方法,在这段时间里,我试图弄清楚以下算法是如何工作的

pop(x)=-sum(x<<i)   where i=0:31

我认为在计算x的每个值之后,我们会得到

x+2*x+4*x+8*x+16*x+..............+2^31*x  =4294967294*x

如果我们将它乘以-1,我们得到-4294967294*x,但是它如何计算位数?请帮助我很好地理解这个方法。谢谢

【问题讨论】:

  • 此方法无效。如果您认为它确实有效,请将其编写在代码中并进行测试。
  • 访问此站点:graphics.stanford.edu/~seander/bithacks.html 它解释了您需要的每一个位操作。
  • 你确定你有这个权利吗?如果我理解你的符号,那么输入x=8(例如)给出二进制11111111 11111111 11111111 11111000的总和,所以-sum是二进制00...001000 =十进制8。但是当我手动计算位时,我得到了答案 1.
  • 它实际上似乎为每个 x 返回 pop(x) == x
  • 这意味着您应该在发布之前尝试过x 的几个值(就像这里的每个人一样)。

标签: c++ bitcount


【解决方案1】:

我相信你的意思

Hacker's Delight 书的封面所示,其中符号表示左-旋转而不是左-移位,这将产生错误的结果和否决票。

此方法之所以有效,是因为旋转将导致 x 的所有二进制数字出现在所有术语中的每个可能的位中,并且因为 2 的补码。

举一个更简单的例子。考虑只有4个二进制数字的数字,其中数字可以表示为ABCD,那么求和意味着:

  ABCD  // x <<rot 0
+ BCDA  // x <<rot 1
+ CDAB  // x <<rot 2
+ DABC  // x <<rot 3

我们注意到每一列都有 A、B、C、D。现在,ABCD 实际上的意思是“2³ A + 2² B + 2¹ C + 2⁰ D”,所以总和就是:

  2³ A        + 2² B        + 2¹ C        + 2⁰ D
+ 2³ B        + 2² C        + 2¹ D        + 2⁰ A
+ 2³ C        + 2² D        + 2¹ A        + 2⁰ B
+ 2³ D        + 2² A        + 2¹ B        + 2⁰ C
——————————————————————————————————————————————————————
= 2³(A+B+C+D) + 2²(B+C+D+A) + 2¹(C+D+A+B) + 2⁰(D+A+B+C)
= (2³ + 2² + 2¹ + 2⁰) × (A + B + C + D)

(A + B + C + D) 是 x 的人口数, (2³ + 2² + 2¹ + 2⁰) = 0b1111 在 2 的补码中是 -1,所以总和是人口数的负数。

该参数可以很容易地扩展到 32 位数字。

【讨论】:

    【解决方案2】:
    #include <stdio.h>
    #include <conio.h>
    
    unsigned int f (unsigned int a , unsigned int b);
    
    unsigned int f (unsigned int a , unsigned int b)
    {
       return a ?   f ( (a&b) << 1, a ^b) : b;
    }
    
    int bitcount(int n) {
        int tot = 0;
    
        int i;
        for (i = 1; i <= n; i = i<<1)
            if (n & i)
                ++tot;
    
        return tot;
    }
    
    int bitcount_sparse_ones(int n) {
        int tot = 0;
    
        while (n) {
            ++tot;
            n &= n - 1;
        }
    
        return tot;
    }
    
    int main()
    {
    
    int a = 12;
    int b = 18;
    
    int c = f(a,b);
    printf("Sum = %d\n", c);
    
    int  CountA = bitcount(a);
    int  CountB = bitcount(b);
    
    int CntA = bitcount_sparse_ones(a);
    int CntB = bitcount_sparse_ones(b);
    
    printf("CountA = %d and CountB = %d\n", CountA, CountB);
    printf("CntA = %d and CntB = %d\n", CntA, CntB);
    getch();
    
    return 0;
    
    }
    

    【讨论】:

    • 请提供有关您的方法的更多信息
    猜你喜欢
    • 1970-01-01
    • 2014-01-27
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 2013-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多