1つの整数が2の何回のべき乗であることを求めます(きわめて効率的です)

41703 ワード

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);
1つの数が2のべき乗であるかどうかを判断し、真であれば2のべき乗である:
#define is2power(a) (((a) & ((a)-1)) == 0)
余を求めるビット演算版が見つかりました...
#define dmod((a),(b)((a)&((b)−1))は、a%bが2であるべきべき乗に等しい
効率的なようです.記録を残す.