怎样快速判断掩码第一个为1的Bit位置
来源:互联网 发布:淘宝直通车新手操作 编辑:程序博客网 时间:2024/05/18 03:54
怎样快速判断掩码第一个为1的Bit位置
作者:lioqio
那么,如何根据Use_Mask得到为1位的位置呢,比较直接的方法如下:
int GetUnUseMem(U32 UseMask)
{
int i;
U32 temp=UseMask;
for(i=0;i<32;i++)
{
if(temp &0x00000001)
return i;
temp= temp>>1;
}
return -1;
}
显然,用这种方法可以得到期望的结果,但是该函数的计算量是与输入参数的内容相关的,最坏情况的运算时间可能是最好情况的32倍。这在一些实时要求比较高的系统中是很难接受的。同时,在函数代码中存在循环,判断分支,也非常不适合当前具有预取指令,乱序执行等功能的处理器提高其性能。当然,我们可以将循环展开,定义寄存器变量等技巧来解决一部分问题,但是是否有其它方法吗。这里考虑了两种方案,抛砖引玉:
1、查找表
该方法一般在掩码长度为8位时比较常见,即定义一个数组X,数组长度为2 的n次方,n为掩码的长度。如掩码为8位时可定义一个256个单元的数组,数组第m个单元初始化为但掩码值为m时其第一个为1位的位置,比如m=0xF4,则11110100b,其第一个为一的位在bit2上,则X[m]=2,同理但X[0xF5]=0,当然X[0x00]=-1。有了这张表,那么查找比特1位置的函数实现很简单:int X[256]={-1,0,1,0,...}
int GetUnUseMem(U8 UseMask)
{
return X[UseMask];
}
那么问题是当UseMask为32位时怎么办,难道构建2的32次方长度的数组吗,也即4G个单元,当然不好,除非你要想搞死你的机器。那就分段处理吧。
int GetUnUseMem(U32 UseMask)
{
int Ret;
if((Ret= X[UseMask&0xFF])>=0) goto GetUnUseMem_End;
if((Ret= (X[UseMask&0xFF00 >>8] +8))>=0) goto GetUnUseMem_End;
if((Ret= (X[UseMask&0xFF0000 >>16] +16))>=0) goto GetUnUseMem_End;
Ret= X[UseMask&0xFF000000 >>24] +24;
GetUnUseMem_End:
return Ret;
}
如果是64位的掩码呢,最多要判断8次,显然不合适,因此可以使用两级解码,第一级掩码中一位代表下一级掩码的相应8位是否有1。
int X[256]={-1,0,1,0,...}
U8 Y[256]={0,0,8,0,16, 0 ,...}
int GetUnUseMem(U8 UseMask1,U64 UseMask)
{
register U8 index = Y[UseMask1];
index = (U8)(UseMask2>>index & 0xFF);
return X[index ];
}
2、位运算
使用位运算可以更快的得到,也不需要用查找表占用内存空间,由于访问内存非常影响处理器的效率,而使用这种方式会使用寄存器或者CPU缓存,不通过北桥再经过DDRII内存控制器得到,因此效率比查找表要高。int GetUnUseMem(U32 UseMask)
{
register U32 index = UseMask ;
//将第一个为1位的低位都置1,其它位都置0
index = (index-1) & ~index;
//得到有多少为1的位
index = (index&0x55555555) + ((index>>1)&0x55555555);
index = (index&0x33333333)+ ((index>>2)&0x33333333);
index = (index&0x0F0F0F0F)+ ((index>>4)&0x0F0F0F0F);
index = (index&0xFF) + ((index&0xFF00) >> 8) + ((index&0xFF0000) >> 16) + ((index&0xFF000000) >> 24);
//得到位数,如果为32则表示全0
return (int)(index);
}
- 怎样快速判断掩码第一个为1的Bit位置
- 怎样快速判断掩码第一个为1的Bit位置
- 怎样快速判断掩码第一个为1的Bit位置
- 对于针对字符串位置的操作,第一个位置被标记为1。
- 计算非0的64位数据中第一个为1的位的位置
- 写一段函数,计算无符号32位整数从高到低,第一个‘1’的位置。(例如,0x0F000000的第一个‘1’的位置为5)
- 如何快速判断一个正整数中只有一个BIT位为1
- 怎样快速判断一个数组中,和值(任意1个或几个的和) 是否等于某值:
- 获得32位数二进制位的第一个1的位置
- poj 2828 Buy Tickets(树状数组找部分和为k的第一个位置)
- 线段树寻找部分和为k的第一个位置
- 判断第二个序列是否为第一个序列的弹出顺序
- 快速排序 以第一个元素为中轴 并测试1000000个整形元素的速度
- 怎样做创业的第一个决定
- 怎样获得listview的第一个item?
- 第一个不同字符的位置
- 快速排序第一个为基准c语言版
- 快速排序 以第一个,中间,最后元素的平均值为中轴 并测试1000000个整形元素的速度
- 一步一步学Linq to sql(一):预备知识
- PetShop4研究----架构设计浅谈
- VC++ Windows窗口处理函数【固定窗口】
- 取字符串长度
- 转》》程序员每天该做的事
- 怎样快速判断掩码第一个为1的Bit位置
- string的字符串替换函数,类似于CString的Replace
- 通用--定时跳转(Javascript结合Asp.net)
- DateTime做主键的获取(一)
- 敬业
- 单向ACL总结
- DateTime 做主键(二)
- string字符串大小写函数
- 控件Repeater的嵌套使用