如何快速找出一个32位二进制数的第几位开始为1

rwxdfbb 2013-04-02 12:47:22
例如一个unsigned int a = 0x21000000;//二进制是00100001 00000000 00000000 00000000
那么第2位[0位开始]为1,则返回2, a = 0x01a00000; 则返回7,一下是实现算法:

//unsigned int a = 0x20000000;//二进制是00100000 00000000 00000000 00000000
int fun(unsigned int x)
{
for(int i=0; i<32; ++i)
{
if( (x<<i) & 0x80000000)
return i;
}
return -1;
}

上述用到了循环,感觉效率不高,不知道有没有更好更快捷的算法?
...全文
1663 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
Hony杨 2013-04-03
  • 打赏
  • 举报
回复
1. log有对应的浮点指令:fyl2x, st(1) := st(1)*log2(st), pop,效率一般,我这边仅仅是提供一种思路而已。 2. 如果LZ是想用在code里面,最好使用内嵌汇编写成宏的形式,指令就是9楼说的“BSR”即可,例如:
#define left_one(a) ({ \
	int _res = -1; \
	__asm__("bsr %0,%%eax":"=r"(_res):"a"(a)); \
	_res;})
rwxdfbb 2013-04-03
  • 打赏
  • 举报
回复
多谢各位,姑且先用循环方法吧,对循环内部稍作调整,采用查表和比较的方法,应该比移位和与运算效率要高一点点,等有好的算法再试吧!
FancyMouse 2013-04-03
  • 打赏
  • 举报
回复
bsf/bsr吧。返回index的没有啥好的位运算办法。就算有也是很不实用的。
dracularking 2013-04-02
  • 打赏
  • 举报
回复
引用 7 楼 dracularking 的回复:
感觉这样效率已经不错了,像log的运算效率应该还低 根据第一位1出现位置的分布概率,可以考虑不从左向右搜,比如从中间向两边搜起,像1楼说的折半查找
可能也是画蛇添足,不搜到最后是不知道是否还有1的
dracularking 2013-04-02
  • 打赏
  • 举报
回复
感觉这样效率已经不错了,像log的运算效率应该还低 根据第一位1出现位置的分布概率,可以考虑不从左向右搜,比如从中间向两边搜起,像1楼说的折半查找
rwxdfbb 2013-04-02
  • 打赏
  • 举报
回复
引用 3 楼 HuiyuYang_fish 的回复:
n = 31 - (int)(log((double)a)/log2).
姑且认为这个是方法二,循环采用的为方法一,对这两个方法分别进行了10万次测试,所用时间如下: 当1的位置位于开始的时候:方法一:0.29ms,方法二:5.89ms 当1的位置位于中间的时候:方法一:1.71ms,方法二:5.88ms 当1的位置位于结束的时候:方法一:4.64ms,方法二:7.61ms 随即数没有进行测试,估计应该和1在中间的位置差不多,可见循环虽然占用代码较多,但是所用时间较少,采用log方法代码简练,但是占用时间较多,当然,我的数据量比较小,总共才32位,用log发挥不出优势,如果是位数更多的情况,应该用log的方法性能会更好。
剑有偏锋 2013-04-02
  • 打赏
  • 举报
回复
我就知道查表
rwxdfbb 2013-04-02
  • 打赏
  • 举报
回复
引用 3 楼 HuiyuYang_fish 的回复:
n = 31 - (int)(log((double)a)/log2).
果然很NB,简单试了下,可以不用循环就得到结果,就是不知道C语音的log算法效率高不高,如果计算log的效率没有平均循环高,会不会得不偿失?不过这已经不重要了,关键是学到了一个新方法哈。 另外还有一个疑问,这种方法有没有大小端的问题?
Hony杨 2013-04-02
  • 打赏
  • 举报
回复
n = 31 - (int)(log((double)a)/log2).
rwxdfbb 2013-04-02
  • 打赏
  • 举报
回复
记得以前看过编程之美上讲过一个找出二进制位中有几个1的算法,除查表外,最后的算法,循环次数只跟1的个数有关,可惜这里用不上,不知道这里能不能不用循环,一下子找出值n?
寻开心 2013-04-02
  • 打赏
  • 举报
回复
1 你可以事先把32个数值定义了: 0x1, 0x2, 0x4, 0x8, 0x10, 0x11, ...... 判断的语句能快一点点 2 你可以用各种查找算法 比如:折半查找办法 就你这个数量级的问题来说,引入别的算法带来的代码的复杂性让整个结果得不偿失 最快捷高效的恐怕还是得用汇编语言去重写

33,009

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧