对于2位的二进制数,求其中1的个数。有一个奇妙的算法。

(设X , y,z 代表二进制中一位比特位的值)(>>右移,&按位与(都为1才为1))

已知 i (X1 X2),j = (0 X1)。 则 i-j 所对应的的十进制数就是 i  中1的个数。其中 j = ( i>>1) & 01。

i j i - j
00 00 00
01 00 01
10 01 01
11 01 10

那么对于一个 int 类型 32位的数,我们以2比特位为块进行划分 i  。对应的 i 和 j 如下。

i  = (X1 X2   X3 X4   X5 X6  ...   X31 X32)B

j  = (0 X1     0 X3     0 X5   ...     0 X31) B  。j = (i  >> 1) & 0x5555 5555;(0x5555 5555 = 0101 0101 0101....0101 B)

n = i - j = (y1 y2    y3 y4    y5 y6 ... y31 y32 )B;此时 n 中 每2比特位对应 i 中每2位比特位 1 的个数。

再将n 每 2比特位合并到一起:

2比特块合并为3比特块:m = (n & 0x3333 3333) + ((n >> 2) & 0x3333 3333);( 0x3333 3333 = 0011 0011 0011...0011B)

(2比特最大表示十进制为3(11B),相加最大为6(011B + 011B = 110B),溢出1位(由后置前的第3位))

n & 0x3333 3333:             00  y3 y4     00 y7 y8 ...  00 y31 y32

+ ((n >> 2) & 0x3333 3333):    00  y1 y2    00  y5 y6 ...  00 y29 y30

—————————————————————————————————

m =  0  z1 z2 z3       0  z4 z5 z6 ...   0 z19 z20 z21       0 z22 z23 z24

(此时每3比特位对应 i 中每3位比特位 1 的个数)

3比特块合并为4比特块:k = (m + (m >> 4)) & 0x0F0F 0F0F;

(0x 0F0F 0F0F = 0000 1111 0000 1111 ...1111 B)

(同理,两个3比特位相加最大表示7+7 = 14(0111B + 0111B = 1110B),溢出1位(由后置前第4位))

m:          0  z1 z2 z3       0  z4 z5 z6 ...   0 z19 z20 z21       0 z22 z23 z24

+ m>>4:      0   0   0   0       0  z1 z2 z3 ...   0 z16 z17 z18       0 z19 z20 z21

————————————————————————————————

k =     0 0 0 0     b1 b2 b3 b4         0 0 0 0   b5 b6 b7 b8     ....         0  0  0  0     b13 b14 b15 b16

(此时每4比特位对应 i 中每4位比特位 1 的个数)

所有4比特块合并到一个5比特块: p = k * 0x01010101;

(* 0x0101 0101= (k << 24) + (k << 16) + (k << 8) + k)

(两个全1的8比特位数相加,会溢出1位(由后置前第9位))

k:           0   0  0  0       b1 b2 b3 b4           ...             ...                    0  0  0  0     b13 b14 b15 b16

k<<8:     0   0  0  0       b5 b6 b7 b8        ...    0 0 0 0     b13 b14 b15 b16                     0000 0000

k<<16:   0   0  0  0       b9 b10 b11 b12         0 0 0 0     b13 b14 b15 b16   0000 0000  0000 0000

+ k<<24:   0   0  0  0       b13 b14 b15 b16       0 0 0 0    0  0  0  0                0000 0000   0000 0000

p  =   0 0 0 c1    c2 c3 c4 c5    0000  0000  0000 0000 0000 0000

最后将前8位比特位就是该数2进制中1的个数:Num_of_1 = p >> 24;

Num_of_1  =  0000  0000  0000 0000 0000 0000     000c1    c2 c3 c4 c5

int Num_of_1(int n)
{n = n -((n >> 1) & ( 0x55555555));n = (n & 0x33333333) + ((n >> 2) & 0x33333333);return (((n + (n >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}
/*循环*/
int Num_of_1(int n)
{int count = 0;while(n){++count;n &= n-1;}return count;
}

不使用循环,求二进制中1的个数相关推荐

  1. 编程之美2.1 求二进制中1的个数

    最近一段的时间,一直在看编程之美之类的算法书籍,刚开始看编程之美,感觉到难度太大,有时候也不愿意去翻动这本书,不过,经过一段时间的修炼,我也彻底的喜欢上这本书了, 书中的算法涉及到很多方面,树,链表, ...

  2. 第2章 数字之魅——求二进制中1的个数

    求二进制中1的个数 问题描述 对于一个字节(8bit)的变量,求其二进制表示中"1"的个数,要求算法的执行效率尽可能地高. [解法一] 可以举一个八位的二进制例子来进行分析.对于二 ...

  3. 求二进制中1的个数(编程之美2.1)

    行文脉络 解法一--除法 解法二--移位 解法三--高效移位 解法四--查表 扩展问题--异或后转化为该问题 对于一个字节(8bit)的变量,求其二进制"1"的个数.例如6(二进制 ...

  4. 编程之美 2.1 求二进制中1的个数

    问题描述: 对于1个字节(8bit)无符号整型变量,求其二进制表示中"1"的个数 解法一:除2取余 (对于二进制操作,除以一个2,原来的数字会减少一个0.如果除的过程中有余数,就表 ...

  5. 【算法】布赖恩·克尼根算法——天才算法求二进制中1的个数

    题目背景 做leetcode第461题汉明距离的时候,发现一个很骚的求1的个数的算法,大呼牛逼! 其实题目本身思路不难,就是求异或然后算1个个数,只是没有想到还可以用这么骚的方式来求. 布赖恩·克尼根 ...

  6. 【博客177】二进制中1的个数:方法三

    内容: 记录求二进制中1的个数的另一种好方法:汉明重量计算算法 最近在看redis源码,发现redis求二进制中1的个数的方法很赞,记录一下: 代码: int vpSWAR(int i) {i = ( ...

  7. 说一说,求一个正整数的二进制中0的个数

    昨天突然看到一个算法题:一个正整数a的二进制中0的个数: 话说这是个老题了,直观的算法就每次右移一位,直到0为止:代码就省略了: 仔细想想有更好的方案么? 就是这个题可以转换成一个正整数~a的二进制中 ...

  8. C/C++求一个整数的二进制中1的个数(用三种效率不同的方法实现)

    题目: 实现一个函数,输入一个整数,输出该数二进制中1的个数.例如把9表示成二进制是1001,有2位是1,因此如果输入是9,该函数输出2 第一种解法(死循环) 判断整数二进制表示中最右边的一位是不是1 ...

  9. C/C++求一个整数的二进制中1的个数

    求一个整数的二进制中1的个数 收藏 题目:输入一个整数,求该整数的二进制表达中有多少个1.例如输入10,由于其二进制表示为1010,有两个1,因此输出2. 分析:这是一道很基本的考查位运算的面试题.包 ...

最新文章

  1. 企业不要求工程师资格认证_谁说工程师不能成为企业家?
  2. js实现表格的增删改查
  3. Hyperledger Fabric 管道(3) 如何做到数据隔离?
  4. Visual Studio 2008 当页面进行调试时,IE8浏览器显示的是空白页面?
  5. ansible roles和django项目的整合
  6. 小米4刷centos_给大家推荐两款小米的产品
  7. onenote同步速度慢
  8. (亲测可用)Redis远程连接频繁掉线应对策略 -- 还能让你不知不自觉中在笑声中掌握Redis命令
  9. 生活小技巧 | win10开热点给手机使用
  10. 如何进行手机投屏设置,屏幕传输达到最快速度
  11. Java中未加入修饰符_(整理)java修饰符
  12. dataBinding 理解
  13. RNA-ATTO 390|RNA-ATTO 425|RNA-ATTO 465|RNA-ATTO 488|RNA-ATTO 495|RNA-ATTO 520近红外荧光染料标记核糖核酸RNA
  14. 融资数据采集以及分析风险投资数据
  15. c语言中的比较大小问题
  16. 光速搭建centos7虚拟机
  17. 了解交换机基本原理与配置
  18. [C++]-Windows下获取CPU、内存利用率
  19. Attention Mechanisms in Computer Vision: A Survey(一)
  20. vcenter 起不来报错VMware ESX 找不到虚拟磁盘“vCenter Server 7.0U3_12.vmdk”。请确认路径有效并重试

热门文章

  1. matlab离散系统差分求全响应,实验七(1)
  2. linux每个月清理命令,总结linux清理垃圾命令
  3. 你长痘吗?留下痘印吗?民间秘方
  4. 无刷直流电机最强科普(收藏版)
  5. 英语发音规则---字母组合oo的发音规律
  6. 购买服务器,80端口的开启
  7. win10自动聚焦无法更换壁纸
  8. oracle 统计同比 环比,oracle求同比,环比函数(LAG与LEAD)的详解
  9. nginx反向代理,隐藏服务IP
  10. 程序猿的血泪史:一定要有数据备份的思想,不然死都不知道咋死的!!!