统计二进制中1的个数
来源:互联网 发布:复旦管院 知乎 编辑:程序博客网 时间:2024/05/17 22:57
题目:统计一个无符号数中的二进制表示中1的个数。
此算法名为平行计算法。基本思想如下:
先两两(两个二进制位)分组统计每组出现的1的个数,而每组1的个数只可能是0个(00),1个(01)或2个(10),由(相加所得的)两位的二进制完全可以表示每组(两个二进制数)中1的个数;接着四四(4个二进制位)的分组,每组内有两个分别用两位二进制数表示的数字,而这些两位二进制数字又是上一步得来的表示1的个数的,因此在每组内把每两位二进制数当作一个整体的数字来相加,就可以看出四四分组的每四个二进制里面有多少个1;以此类推......
下面这张图很直观(来源于网络)
但是图片不足以说明我们求解的逻辑过程:例a=1001011101111101(16-bits)
1.两两分组,求每组的1的个数
+ 0
——————————————————————
注意:上下两个二进制数才是一组,这样才能实现组内相加,
那么怎样用语言来实现呢?
肯定是两个二进制数相加来表示的,下面那个只留了8-bits的偶数位,只需把其与0101010101010101相与即可,即1001011101111101&0101010101010101(0x5555)=0001010101010101(01111111),另一个是只留了奇数位,1001011101111101&1010101010101010(0xAAAA)=1000001000101000,得到的这个位模式不能与上面的那个偶数位直接相加(那不等于原来的数了么),因为它是向右偏移了一位的(实质上对于原数而言,应该是第1位与第0位相加,第3位与第2位相加...第15位与第14位相加),很显然,把我们得到的结果右移1位变为0100000100010100即可。
综上,两两分组组内相加的最终表示就是(a&0x5555)+((a&0xAAAA)>>1);
2.四四分组,组内相加,求1的个数(原数变为0101 0110 0110 1001)
+
——————————————————
怎样由0101 0110 0110 1001变为0001 0010 00100001(只保留每组的低两位),原数与0x3333相与即可,
怎样由0101 0110 0110 1001变为0001 0001 00010010(只保留每组的高两位),原数与0xCCCC相与是不够的,同样存在1中的问题,把相与的结果右移两位即可.
3.......
其实,问题的核心在于如何把每组的高位和低位剥离,实现组内相加,总结起来就一句话,用的着的位用1相与保留,不用的与0相与置0,组内的空位(在高位)用0补齐(16位),最后,不要忘了移位!
参考资料:http://everything2.com/title/Counting+1+bits
- 统计二进制中1的个数
- 统计二进制中1的个数
- 二进制中1的个数统计
- 统计二进制数中1的个数
- 统计二进制中1的个数
- 统计二进制正整数中1的个数
- 统计二进制数中1 的个数
- 统计二进制中1的个数
- 二进制中1的个数统计
- 统计二进制中1的个数
- 统计二进制数中1的个数
- OJ_0277.统计二进制中1的个数
- 统计二进制数中1的个数
- 快速统计二进制中1的个数
- 统计二进制数中“1”的个数(懂二进制)
- 统计一个整数中二进制中1的个数
- 统计整数的二进制表示中1的个数
- 统计数x的二进制表示中1的个数
- windows下载安装redis
- 求两个链表的相交节点(算法)
- C的几个简答题
- 堆和栈的区别(windows内存管理)
- UESTC 方老师与素数
- 统计二进制中1的个数
- 为什么C语言中bool型变量占用一个字节
- 希尔排序
- 编辑工具
- 一次jvm调优实战
- geoserver 中points 制定sld样式 学习笔记
- Day13持久化存储——SQLite数据库存储
- 导航类视图之UITabBarController
- Unicode