variable-precision SWAR算法:计算Hamming Weight

转自我的Github

最近看书看到了一个计算Hamming Weight的算法,觉得挺巧妙的,纪录一下。

Hamming Weight,即汉明重量,指的是一个位数组中非0二进制位的数量。

对于这个问题,最直观的算法就是遍历二进制位,时间复杂度是O(n),每次需要遍历n个位。另外一个算法是查表,用一个数组记录下一定位数每个数值的汉明重量如:数组hwTable=[0, 1, 1, 2]纪录了0, 1, 2, 3的汉明重量。这个算法的时间复杂度也是O(n),但是不需要执行n次,而是只需要执行n/m次,m取决于查表一次能够决定的二进制位的长短,这个算法需要使用额外的空间为O(m^2)。

而我们接下来的所提到的SWAR算法既有着较高的效率,又不需要使用那么大的空间,算法实现如下:

// 计算32位二进制的汉明重量
int32_t swar(int32_t i)
{
i = (i & 0x55555555) + ((i >> ) & 0x55555555);
i = (i & 0x33333333) + ((i >> ) & 0x33333333);
i = (i & 0x0F0F0F0F) + ((i >> ) & 0x0F0F0F0F);
i = (i * (0x01010101) >> );
return i
}

计算32位的位数组只需要O(1),而且比查表法需要的空间更少。

乍一看好像看不出什么头绪,只要动手一步步之行一下这个算法就可以看到它的巧妙之处。下面我们一步步执行一下这个算法:

:     :     F:
input:
step1: (i&0x55555555)
((i>>)&0x55555555)
(+) step2: (i&0x33333333)
((i>>)&)
(+) step3: (i&0x0F0F0F0F)
((i>>)&0x0F0F0F0F)
(+) step4: ...

可以清楚的看到,第一步的结果中,每两位为一组,纪录了这两位里面非0位的个数;第二步的执行结果中,每四位为一组,纪录了每四位里面非0位的个数;第三步的结果中,每八位为一组,纪录了每八位里面非0位的个数;第四步只要想想笔算乘法就清楚了^_^。当然如果一次要计算六四位也是可以的。。

这个是目前已知效率最好的计算汉明重量的通用算法,在redis的bit array中也有使用,不过redis中将SWAR算法和查表法结合起来了。

variable-precision SWAR算法:计算Hamming Weight的更多相关文章

  1. variable precision SWAR算法

    计算二进制形式中1的数量这种问题,在各种刷题网站上比较常见,以往都是选择最笨的遍历方法“蒙混”过关.在了解Redis的过程中接触到了variable precision SWAR算法(以下简称VP-S ...

  2. variable-precision SWAR算法介绍

    BITCOUNT命令是统计一个位数组中非0进制位的数量,数学上称作:”Hanmming Weight“ 目前效率最好的为variable-precision SWAR算法,可以常数时间内计算出多个字节 ...

  3. Hamming Weight的算法分析(转载)

    看代码时遇到一个求32bit二进制数中1的个数的问题,感觉算法很奇妙,特记录学习心得于此,备忘. 计算一个64bit二进制数中1的个数. 解决这个问题的算法不难,很自然就可以想到,但是要给出问题的最优 ...

  4. 统计无符号整数二进制中1的个数(Hamming weight)

    1.问题来源 之所以来记录这个问题的解法,是因为在在线编程中经常遇到,比如编程之美和京东的校招笔试以及很多其他公司都累此不疲的出这个考题.看似简单的问题,背后却隐藏着很多精妙的解法.查找网上资料,才知 ...

  5. [算法]从一道题引出variable-precision SWAR算法

    苏君君出了一道题,是牛客网上面的: 输入一个int型整数,输出该数二进制表示中1的个数.其中负数用补码表示. 其实这道题并不难,大家很容易想到的解法是转成字符串的思路,即如下所示: public st ...

  6. Fp关联规则算法计算置信度及MapReduce实现思路

    说明:參考Mahout FP算法相关相关源代码. 算法project能够在FP关联规则计算置信度下载:(仅仅是单机版的实现,并没有MapReduce的代码) 使用FP关联规则算法计算置信度基于以下的思 ...

  7. Canopy算法计算聚类的簇数

    Kmeans算是是聚类中的经典算法.步骤例如以下: 选择K个点作为初始质心 repeat 将每一个点指派到近期的质心,形成K个簇 又一次计算每一个簇的质心 until 簇不发生变化或达到最大迭代次数 ...

  8. 分类模型的F1-score、Precision和Recall 计算过程

    分类模型的F1分值.Precision和Recall 计算过程 引入 通常,我们在评价classifier的性能时使用的是accuracy 考虑在多类分类的背景下 accuracy = (分类正确的样 ...

  9. 利用CORDIC算法计算三角函数

    这里主要先介绍如何利用CORDIC算法计算固定角度\(\phi\)的\(cos(\phi)\).\(sin(\phi)\)值.参考了这两篇文章[1].[2]. 一般利用MATLAB计算三角函数时,用\ ...

随机推荐

  1. Node.js学习(14)----EJS模板引擎

    这个入门教程将从以下几个方面来讲解: 1. 引入EJS 2. 创建一个模板 3. 使用视图工具组件 4. 使用错误处理组件 5. 什么情况下应使用EJS 引入EJS 在我们正式开始前,我们先来做点准备 ...

  2. Android框架结构图

  3. node.js在windows下的学习笔记(1)---安装node.js

    1.首先打开http://www.nodejs.org/ 2.选择DOWNLOADS,跳转到下面的画面,我的系统是windows7的32位.所以选择.msi的32bit版本. 3.下载后,得到一个5. ...

  4. Android 颜色渲染(六) RadialGradient 环形渲染

    Android 颜色处理(六) RadialGradient 环形渲染 public RadialGradient(float x, float y, float radius, int[] colo ...

  5. JSON数据的中文乱码问题

    问题描述: 在firefox中返回的JSON数据没有出现乱码,但在GridPanel中显示乱码,而jsp页面和xml文件都是utf-8类型. 解决方案: 在 PrintWriter out = res ...

  6. 容器大小的改变以及容器操作可能使迭代器失效、vector对象的容量变化

    1 改变容器的大小 我们可以使用resize来增加或缩小容器,与往常一样,array不支持resize.如果当前大小大于所要求的大小,容器后面的元素会被删除:如果当前大小小于新大小,会将新元素添加到容 ...

  7. 数据持久层(三)ODB介绍

    ODB: C++ Object-Relational Mapping (ORM) ODB is an open-source, cross-platform, and cross-database o ...

  8. 【转】Hibernate映射机制之XXX.hbm.xml

    http://blog.csdn.net/a9529lty/article/details/6454924[注意多对一中“多”和“一”各自的java文件.xml文件的书写格式] 另外两篇总结:http ...

  9. iOS之AlertController的使用

    iOS 8的新特性之一就是让接口更有适应性.更灵活,因此许多视图控制器的实现方式发生了巨大的变化.全新的UIPresentationController 在实现视图控制器间的过渡动画效果和自适应设备尺 ...

  10. 初识hibernate

    //针对myEclipse2014版本 怎样新建一个工程实现这些东西的导入. 打开myeclipse. 2.点击右上角的open perspective 找到这个 MyEclipse Database ...