• 求整型中二进制1的个数


    1. 确定二进制1的个数:

     ->循环死&
     
     ->x-1&x
     
     ->查表,分写死与动态生成,动态生成方法:BitsSetTable256[i] = (i &1) + BitsSetTable256[i /2];
     
     ->并行位运算:
        
        int BitCount4(unsigned int 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) &0x0000ffff) ;

        return n ;
    }

    ->算法法:
        将n的二进制表示写出来,然后每3bit分成一组,求出每一组中1的个数,再表示成二进制的形式。比如n = 50,其二进制表示为110010,分组后是110和010,这两组中1的个数本别是2和3。2对应010,3对应011,所以第一行代码结束后,tmp = 010011,具体是怎么实现的呢?由于每组3bit,所以这3bit对应的十进制数都能表示为2^2 * a + 2^1 * b + c的形式,也就是4a + 2b + c的形式,这里a,b,c的值为0或1,如果为0表示对应的二进制位上是0,如果为1表示对应的二进制位上是1,所以a + b + c的值也就是4a + 2b + c的二进制数中1的个数了。举个例子,十进制数6(0110)= 4 * 1 + 2 * 1 + 0,这里a = 1, b = 1, c = 0, a + b + c = 2,所以6的二进制表示中有两个1。现在的问题是,如何得到a + b + c呢?注意位运算中,右移一位相当于除2,就利用这个性质!


    4a + 2b + c 右移一位等于 2a + b
    4a + 2b + c 右移量位等于a
    然后做减法

    4a + 2b + c –(2a + b) – a = a + b + c,
    这就是第一行代码所作的事,明白了吧。

    ②.在第一行的基础上,将tmp中相邻的两组中1的个数累加,由于累加到过程中有些组被重复加了一次,所以要舍弃这些多加的部分,这就是&030707070707的作用,又由于最终结果可能大于63,所以要取模。

    需要注意的是,经过第一行代码后,从右侧起,每相邻的3bit只有四种可能,即000, 001, 010, 011,为啥呢?因为每3bit中1的个数最多为3。所以下面的加法中不存在进位的问题,因为3 + 3 = 6,不足8,不会产生进位。

    tmp + (tmp >> 3)-这句就是是相邻组相加,注意会产生重复相加的部分,比如tmp = 659 = 001 010 010 011时,tmp >> 3 = 000 001 010 010,相加得

    001 010 010 011
    000 001 010 010
    ---------------------
    001 011 100 101
    001 + 101 = 1 + 5 = 6,所以659的二进制表示中有6个1

    注 意我们想要的只是第二组和最后一组(绿色部分),而第一组和第三组(红色部分)属于重复相加的部分,要消除掉,这就是&030707070707 所完成的任务(每隔三位删除三位),最后为什么还要%63呢?因为上面相当于每次计算相连的6bit中1的个数,最多是111111 = 77(八进制)= 63(十进制),所以最后要对63取模。

  • 相关阅读:
    百度点聚合功能,自定义针头功能
    iOS之极光推送
    iOS之短信认证
    iOS FMDB
    iOS 远程推送
    iOS之本地推送(前台模式与后台模式)
    iOS指纹识别
    关于——GCD
    关于——NSThread
    给label text 上色 && 给textfiled placeholder 上色
  • 原文地址:https://www.cnblogs.com/qqmomery/p/4709089.html
Copyright © 2020-2023  润新知