比特位操作之ffs和fls实现原理

  • FFS

ffs即find the first bit set,查找第一个置1的bit位,从bit0开始找是否置1,32位数值检查完bit31后停止,64位数值检查完bit63后停止。

  • FLS

fls即find the last bit set,查找最后一个置1的bit位,32位数,则从bit31开始找,64位数,则从bit63开始找。检查完bit0后停止。

因为都是查找第一个置1的bit位。只是一个从低bit开始找,一个是从高bit开始找。可以假想一下,第一个置1bit的前面bit都是0的,而第一个置1bit后面的位是不关心的,不管是0还是1,就可以转化为查找一堆bit中置1的bit位,所以这里是可以使用二分法查找。

首先折半以32位数fls为例,首先看前16bit是否是全0,是全0就把后16bit移到前面,此时第一个置1的bit不在前16bit,所以n要减去16。
如果前16bit非0,那就说明置1的bit包含在,前面16bit中了,继续下一步。

依次类推
32位数,按照二分法查找算法步骤需要log2(32)=5步。
64位数,log2(64)=6步。

#include <stdio.h>

// find last bit set, binary search
int __fls(unsigned int v)
{
	int n = 32;

	if (!v) return -1;
	if (!(v & 0xFFFF0000)) { v <<= 16; n -= 16; }
	if (!(v & 0xFF000000)) { v <<=  8; n -= 8;  }
	if (!(v & 0xF0000000)) { v <<=  4; n -= 4;  }
	if (!(v & 0xC0000000)) { v <<=  2; n -= 2;  }
	if (!(v & 0x80000000)) { v <<=  1; n -= 1;  }

	return n - 1;
}

// find last 64bit set, binary search
int __fls64(unsigned long v)
{
	int n = 64;

	if (!v) return -1;
	if (!(v & 0xFFFFFFFF00000000)) { v <<= 32; n -= 32; }
	if (!(v & 0xFFFF000000000000)) { v <<= 16; n -= 16; }
	if (!(v & 0xFF00000000000000)) { v <<=  8; n -= 8;  }
	if (!(v & 0xF000000000000000)) { v <<=  4; n -= 4;  }
	if (!(v & 0xC000000000000000)) { v <<=  2; n -= 2;  }
	if (!(v & 0x8000000000000000)) { v <<=  1; n -= 1;  }

	return n - 1;
}

// find first bit set, binary search
int __ffs(unsigned int v)
{
	int n = 1;

	if (!v) return -1;
	if (!(v & 0x0000FFFF)) { v >>= 16; n += 16; }
	if (!(v & 0x000000FF)) { v >>=  8; n += 8;  }
	if (!(v & 0x0000000F)) { v >>=  4; n += 4;  }
	if (!(v & 0x00000003)) { v >>=  2; n += 2;  }
	if (!(v & 0x00000001)) { v >>=  1; n += 1;  }

	return n - 1;
}

// find first 64bit set, binary search
int __ffs64(unsigned long v)
{
	int n = 1;

	if (!v) return -1;
	if (!(v & 0x00000000FFFFFFFF)) { v >>= 32; n += 32; }
	if (!(v & 0x000000000000FFFF)) { v >>= 16; n += 16; }
	if (!(v & 0x00000000000000FF)) { v >>=  8; n += 8;  }
	if (!(v & 0x000000000000000F)) { v >>=  4; n += 4;  }
	if (!(v & 0x0000000000000003)) { v >>=  2; n += 2;  }
	if (!(v & 0x0000000000000001)) { v >>=  1; n += 1;  }

	return n - 1;
}

void main(void)
{
	int v = 0x00000011;
	long v64 = 0x00C0001000010000;

	printf("v = %x\n", v);
	printf("find first bit set %d\n", __ffs(v));
	printf("find first bit set (same)%d\n", __fls(v & -v));
	printf("find last bit set %d\n", __fls(v));
	printf("find first 64bit set %d\n", __ffs64(v64));
	printf("find first 64bit set (same)%d\n", __fls64(v64 & -v64));
	printf("find last 64bit set %d\n", __fls64(v64));
}
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值