第一次写关于算法的问题。今天数据库课老师在讲数据库底层实现的时候提到了位图索引,最后归结为1的个数,以前看到很多次关于1的个数的计算,今天总结一下。

最开始是有《编程之美》里面的问题引出的:如何最快地读取到二进制中1的个数.

最开始我也是感觉一个个地数不就完了,但是人家说了要求最快。一个个的数是O(N)级的。

1. 比如:int count=0;

for(;x;x>>1)

{

count++;

}//当然也有每次用x直接除以2 的。

2.后来就是用x&(x-1)的结果是否为0来判断,如果为零,有一个1,否则没有。

所以有:

for(;x;count++)

x&=x-1;

3.查表大法,就是一一列举这n位二进制所有的可能到数组中,然后直接查表就是了,这里就不赘述了

4.这个新的方法叫shift and add,正如名字一样,该算法用的就是shift 和add(移位和加法):

对于n位二进制数,最多有n个1,而n必定能由n位二进制数来表示,因此我们在求出某k位中1的个数后,可以将结果直接存储在这k位中,不需要额外的空间。

以4位二进制数abcd为例,最终结果是a+b+c+d,循环的话需要4步加法

那么我们让abcd相邻的两个数相加,也就是 a+b+c+d=[a+b]+[c+d]

[0 b 0 d]

[0 a 0 c]

--------

[e f] [ g h]

ef=a+b   gh=c+d 而 0b0d=(abcd)&0101,0a0c=(abcd)>>1 &0101

[ef]  [gh]再相邻的两组相加

[00 ef]

[gh]

--------

i j k l

ijkl=ef+gh  gh=(efgh)&& 0011 ,ef=(efgh)>>2 & 0011

依次入次递推。需要log(N)次

代码如下:

typedef unsigned __int64 uint64; //assume this gives 64-bits

const uint64 m1 = 0x5555555555555555; //binary: 0101...

const uint64 m2 = 0x3333333333333333; //binary: 00110011..

const uint64 m4 = 0x0f0f0f0f0f0f0f0f; //binary: 4 zeros, 4 ones ...

const uint64 m8 = 0x00ff00ff00ff00ff; //binary: 8 zeros, 8 ones ...

const uint64 m16 = 0x0000ffff0000ffff; //binary: 16 zeros, 16 ones ...

const uint64 m32 = 0x00000000ffffffff; //binary: 32 zeros, 32 ones

int popcount_1(uint64 x) {

x = (x & m1 ) + ((x >> 1) & m1 );

x = (x & m2 ) + ((x >> 2) & m2 );

x = (x & m4 ) + ((x >> 4) & m4 );

x = (x & m8 ) + ((x >> 8) & m8 );

x = (x & m16) + ((x >> 16) & m16);

x = (x & m32) + ((x >> 32) & m32);

return x;

}

5.对shift and add的优化:

看到有三种优化,这里只提两种吧

1

int popcount_2(uint64 x)

{

x -= (x >> 1) & m1;

x = (x & m2) + ((x >> 2) & m2);

x = (x + (x >> 4)) & m4;

x += x >> 8;

x += x >> 16;

x += x >> 32;

return x & 0x7f;

}

2.

int popcount_3(uint64 x) {

x -= (x >> 1) & m1;

x = (x & m2) + ((x >> 2) & m2);

x = (x + (x >> 4)) & m4;

return (x * h01)>>56;

据说这可是MIT的牛人想出来的高招(当时是求余,现在换成除法了更快)

我也是参见了wikipedia(但是看不懂)和http://blog.ibread.net/375/pop-count-problem/上面的文章。

int popcount_3(uint64 x) {

x -= (x >> 1) & m1;

x = (x & m2) + ((x >> 2) & m2);

x = (x + (x >> 4)) & m4;

return (x * h01)>>56;

hamming weight_popcount或者hamming weight(二进制1的个数问题)相关推荐

  1. 位运算n=(n-1)快速统计二进制1的个数

    看到一篇博客,发现n&=(n-1)竟然能够快速统计二进制1的个数,经过博主同意特此拿来分享一下. 首先,分析一下该式子,先可以简化为 n=n&(n-1); 我们先做一个实例, n 1 ...

  2. C++用二进制交换二个数的实现算法(附完整源码)

    C++用二进制交换二个数的实现算法 C++用二进制交换二个数的实现算法完整源码(定义,实现,main函数测试) C++用二进制交换二个数的实现算法完整源码(定义,实现,main函数测试) #inclu ...

  3. Leetcode每日一题:1356.sort-integers-by-the-number-of-1-bits(根据二进制1的个数排序)

    思路:一个简单的思路就是先求出每一个数x的二进制位数count,然后把它加入map的映射中,即x加入m[count]的数组中,map<int ,vector> m:然后m每一个key里面的 ...

  4. 2016: 神殿(求二进制1的个数最多的那个数)

    题目描述: icebound通过勤工俭学,攒了一小笔钱,于是他决定出国旅游.这天,icebound走进了一个神秘的神殿.神殿由八位守护者守卫,总共由6464个门组成,每一道门后都有一个迷宫,迷宫的大小 ...

  5. 编程之美二进制一的个数

    编程之美关于求一个整数二进制数一的个数后面的一道思考题. 1.A和B两个数,将A变成B,所需要改变的数字个数(二进制数). 异或求出异或值二进制包含的1的个数. #include <stdio. ...

  6. 【剑指Offer】二进制1的个数(减1后的数和原数相与,能将最低位的1置0)

    目录 题目描述 思路 题目描述 输入一个整数,输出该数32位二进制表示中1的个数.其中负数用补码表示. 思路 循环操作:减去1后的数和原数相与,能将最低位的1置0 每次操作都会将最低位的1置0,所以能 ...

  7. 测试整数(二进制)含1个数

    引:中国某杀毒软件公司2010年3月笔试题 #include <iostream> using namespace std; int func(int n) {int nCount = 0 ...

  8. 一条语句判断数x是否2的n次幂.求取二进制1的个数

    一条语句判断数x是否2的n次幂 return !(x & (x - 1)); 求取十进制数字元素1的个数 int fun(int x) { int count = 0; int i, j, k ...

  9. C++——二进制输出一个数以及输出double型位数过多情况

    先看程序 unsigned int c = -1; cout << bitset<32>(c) << endl;//输出32个1 cout << c & ...

最新文章

  1. C++STL的queue容器
  2. 使用Infinispan创建自己的Drools和jBPM持久性
  3. zillow房价预测比赛_Kaggle竞赛 —— 房价预测 (House Prices)
  4. db15接口各针脚示意图_【沙发管家】带你了解 HDMI 接口的用处都有哪些?
  5. Notification使用详解之一:基础应用
  6. 全宁对医药行业销售代表的介绍
  7. 观察者模式实际应用:监听线程,意外退出线程后自动重启
  8. 安装linux镜像文件
  9. Java简易小说阅读器
  10. 读书印记 - 《批判性思维工具》
  11. 金蝶服务器选项没有账套信息,金蝶财务软件帐套属性设置保存和帐套启用报错的解决方法...
  12. 基于微信小程序的投票系统源码
  13. 【学习笔记】斯坦福大学公开课(机器学习) 之生成学习算法:朴素贝叶斯
  14. git报 “The stash entry is kept in case you need it again“ 错误解析
  15. 凹入法写入指定目录至文档,并计算目录大小
  16. 手游传奇刷元宝_传奇手游如何刷元宝
  17. xp无法访问win7计算机提示无权限,ghost xp访问win7共享无权限怎么解决
  18. 从输入 URL 到浏览器接收的过程中发生了什么事情?
  19. 转载一条G1垃圾回收器的调优经验
  20. 在 Python 中将秒转换为小时、分钟和秒

热门文章

  1. python super 理解(四)
  2. xgboost防止过拟合
  3. SparkSql读取外部数据源
  4. matplotlib 笔记 imshow
  5. 前端白屏问题_前端优化-如何计算白屏和首屏时间
  6. numpy.divide详解
  7. python 中文乱码问题解决方案
  8. flink DataStream API使用及原理
  9. HBase 数据导入功能实现方式解释
  10. Importing/Indexing database (MySQL or SQL Server) in Solr using Data Import Handler--转载