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. Laravel Quickstart

    Installation Via Laravel Installer First, download the Laravel installer using Composer. composer gl ...

  2. 无法识别的属性“targetFramework”。请注意属性名称区分大小写。错误分析以及解决方案

    我的配置文件中是这样写的,<compilation debug="true" targetFramework="4.0"> 发布在iis上出现了 “ ...

  3. Git简介:

    Git中文文档 1.详解在Visual Studio中使用git版本系统(图文) 2.GitExtensions下载地址:http://gitextensions.codeplex.com/ 3.Gi ...

  4. NASA关于如何写出安全代码的10条军规

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:NASA关于如何写出安全代码的10条军规.

  5. XML 语法规则

    转摘自:http://www.w3school.com.cn/xml/xml_elements.asp XML 语法规则 XML 文档包含 XML 元素. XML 的语法规则很简单,且很有逻辑.这些规 ...

  6. unity3d 获取相机视口四个角的坐标

    功能:如标题所示,主要考虑用来做3d Plane的自适应屏幕 /// <summary> /// 获取指定距离下相机视口四个角的坐标 /// </summary> /// &l ...

  7. cocos2d-x简单动画

    转自:http://4137613.blog.51cto.com/4127613/759610 这里只给出最基本的动画代码,具体使用要根据实际情况自己封装.最好自己开发一个编辑器.额外说一句,开发编辑 ...

  8. Ubuntu 12.04 wine QQ

    1.首先安装最新版的wine1.52,没记错版本号应该是这个 sudo add-apt-repository ppa:ubuntu-wine/ppa sudo apt-get update sudo  ...

  9. POJ 1330 Nearest Common Ancestors(Tree)

    题目:Nearest Common Ancestors 根据输入建立树,然后求2个结点的最近共同祖先. 注意几点: (1)记录每个结点的父亲,比较层级时要用: (2)记录层级: (3)记录每个结点的孩 ...

  10. 每天进步一点达——MySQL——myisampack

    一.        简单介绍 myisampack是一个压缩使用MyISAM引擎表的工具,通常会压缩40%~70%,当须要訪问数据.server会将所须要的信息读入到内存中.所以当訪问详细记录时,性能 ...