快速求一个32位无符号整数二进制中为1的个数
来源:互联网 发布:淘宝代销退货 编辑:程序博客网 时间:2024/05/22 08:02
一个数5,二进制表示法,为101,则有2个1,如何快速求出一个32位无符号整数中1的个数,如果要我们来做,我们可能会进行一个32次的循环,从1至32,依次测试相应的位;这个算法不是最优的。以下算法效率的要快很多:http://aggregate.ee.engr.uky.edu/MAGIC/。源代码如下
unsigned int
ones32(register unsigned int x)
{
/* 32-bit recursive reduction using SWAR...
but first step is mapping 2-bit values
into sum of 2 1-bit values in sneaky way
*/
x -= ((x >> 1) & 0x55555555);
x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
x = (((x >> 4) + x) & 0x0f0f0f0f);
x += (x >> 8);
x += (x >> 16);
return(x & 0x0000003f);
}
刚开始看这段代码,有一点晕,仔细分析一下,还是有点意思的。下面我就逐行分析这个函数
先看第一行代码,x -= ((x >> 1) & 0x55555555);
这行代码的作用是,将相邻两位中1的个数统计出来,我们举个例子,一个数x=abcdefgh
则x>>1=abcdefg,再将上一步的结果与0x55555555相与,0x55555555,这个数有一个特点,从低住高数所有偶数位都为0
,所以与这个数想与的作用是把一个数中所有的偶数位上的1清掉,最后再从X减掉这个数,我们看例子,x=abcdefgh
,((x>>1)&0x55555555)=0a0c0e0g,然后abcdefgh-0a0c0e0g,这里看前两位:gh-0g,这里有4个可能,
第一种可能:g种h都为1,则gh-0g=11-01=10,10正好为十进制的2,表示原数abcdefgh,最后两位gh中有2个1;
第二、三种可能:g种h有一个为1,则gh-0g=10-01,或者是01-00,不管怎么样,最后结果都是01,01为十进制的1,表示原数abcdefgh,最后两位gh中有1个1;
第四种可能:两个都为0,结果也是0,表示原数最后两位gh有0个1。
再来看第二行代码
x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
这行代码的作用是将相邻4位的数加起来,也就是统计原数中相邻4位中1的个数,前面我们说过,第一步得到的结果是原数中相邻两位中1的个数,第一步得到的数连续两位的组合只有三种情况:10,01,00;
第一个表达式:((x >> 2) & 0x33333333)
其作用是将上一步的结果右移两位再与0x33333333相与,作用是将一个数中从低住高数,位置是偶数的连续两位清0,即从低往高数,将第3,4,有点念绕口令的感觉了。我们举个例子, x=abcdefgh,经过((x >> 2) & 0x33333333),则结果是00ab00ef,后面 (x & 0x33333333)),得到00cd00gh,两数相加:00ab00ef+00cd00gh,后四位的结果等于ef+gh,头4位的结果是ab+cd,其作用是第一步的结果以4位为一个单位,两位两位的相加,经过这一步后,每4位就是原数相应4位中1的个数。举个例子01001010,经过这一步,为00010010,头4位0001表示原数头4位有1个1,后4位0010,表示原数后4位有2个1。
第二、三、四行的代码功能差不多,只不过中将相邻4(8、16)位中的数进行两两相加。
最后一步(x & 0x0000003f),因为最多只有32个1,即最大数是32,与3f相与,可把其余位屏蔽掉!
- 快速求一个32位无符号整数二进制中为1的个数
- 快速求一个32位无符号整数二进制中为1的个数
- 求32位无符号整数中比特为1的二进制位数
- 求一个无符号整数转化为二进制后1的个数
- 【编程之美】任意给定一个32位无符号整数n,求n的二进制表示中1的个数
- 判断32位无符号整数二进制中1的个数
- 求32位整数二进制中1的个数
- 练习5: 计算一个32位无符号整数在二进制中1的个数, 顺便熟悉2进制和16进制
- 求一个32位无符号整数右边"0"的个数
- 计算一个无符号整数的二进制中0和1的个数
- 位运算实现反转字节和求二进制整数中1的个数(无循环)
- 求无符号数二进制中1的个数&&求一个字符串中最长的连续子串
- 求32位整数二进制1的个数
- 求一个整数的二进制中1的个数
- 求一个整数的二进制中1的个数
- 求一个整数的二进制中1的个数
- 求一个整数的二进制中1的个数
- 求一个整数的二进制中1的个数
- 修改系统音量(SystemVolume)的方法
- poj 1580
- MYSQL笔记(一)
- Regex.Split 在分割 "|" 符号时出现问题,应该使用 "[|]" 才可以分组
- excel vba入门 更新中...
- 快速求一个32位无符号整数二进制中为1的个数
- 20110528
- 定机票的好网站
- Java调用摄像头进行拍照源码,并且有JMF下载地址
- 由PID得到进程名
- 用getopt处理main函数的参数
- 程序四
- EFL 1.01版本发布!
- 解决 ubuntu11.04下wmv格式文件播放异常