位运算,自低(右)向高(左)逐个地将数位1转置为0

对任意整数n,不妨设其最低(右)的数位对应2^k,于是n的二进制展开应该如下:

          x   x   ...   1 0 0 ...  0 

其中最右边第一次1出现时,数位x可能是0或1,而最低的k+1位必然是“1 0 0  ... 0” ,即数位1之后是k个0。

    于是相应的,n-1的二进制展开应该如下:

          x    x   ...  x   0 1 1 ...  0

也就是说,其最低位的k+1于n恰好相反,其余的(更高位各位相同)。

      因此,二者做与运算(n & (n - 1))的结果应为:

          x    x   ...   x   0 0 0 ...  0

等效于将原n二进制展开的最低位1转置为0。

      举个例子:

            13 的二进制 1 1 0 1 , 最低位的1为0 0 0 1 。第一次将其反置为0,使之1 1 0 0 。

            13-1=12,二进制 1 1 0 0, 13&12 即 1 1 0 1 & 1 1 0 0 ,成功得到 1 1 0 0 。

            12-1=11,二进制 1 0 1 0 , 1 1 0 0 & 1 0 1 0 ,成功消除从右第二位的1,得到 1 0 0 0 。

             8 -1= 7, 二进制 0 1 1 1,   1 0 0 0 & 0 1 1 1 ,成功全部将所有1置位。

int countOnes1 (unsigned int n)
{
    int ones=0;
    while (0 < n)         //在n缩减至0之前,反复
    {
        ones++;
        n &= n-1;          //消除当前最靠右的1
    }
    
    return ones;

}

猜你喜欢

转载自blog.csdn.net/weixin_40539125/article/details/82995523