求一个整数是2的几次幂(极其高效)

1.源自linux内核源码中的一段(有汇编的,不过摘抄的c实现的,并做了一点变形)


汇编的不做比较,记录下而已
Linux/arch/avr32/include/asm/page.h

/* Pure 2^n version of get_order */ static inline int get_order(unsigned long size) {         unsigned lz;         size = (size - 1) >> PAGE_SHIFT;         asm("clz %0, %1" : "=r"(lz) : "r"(size));     return 32 - lz; }



内核中的原版
Linux/arch/mn10300/include/asm/page.h

#define PAGE_SHIFT 12 /* Pure 2^n version of get_order */ static inline int get_order(unsigned long size) __attribute__((const)); static inline int get_order(unsigned long size) {         int order;         size = (size - 1) >> (PAGE_SHIFT - 1);         order = -1;         do {                 size >>= 1;                 order++;         } while (size);         return order; }



小变更后的:

static inline int get_order(unsigned long size) {     int order;     size = (size - 1) >> (0);     order = -1;     do {         size >>= 1;         order++;     } while (size);     return order; }



2.源自lua源码中的一段

int luaO_log2 (unsigned int x) {   static const unsigned char log_2[256] = {     0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,     8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,     8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,     8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,     8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8   };   int l = -1;   while (x >= 256) { l += 8; x >>= 8; }   return l + log_2[x]; }



貌似纯C的话,还是lua的这个函数快吧。

最近的一个小需求是,根据size值,变更为接近2的幂的一个数(还多亏看了下lua源码。。。)。
1<<(luaO_log2(size)+1);
判断一个数是否为2的幂,为真则为2的幂:
#define is2power(a) (((a) & ((a)-1)) == 0)

才发现求余的位运算版。。。
#define dmod((a), (b)) ((a)&((b)-1)) 等于 a%b  b要为2的幂

貌似很高效。留记录。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值