求解一个数的二进制最高位

求解一个数的二进制最高位

求解一个数的二进制最高位是一个常见问题。具体来说,5 的二进制是 101,其最高位在第 2 位(假定最低位是0)。30 的二进制是 11110,最高位是第 4 位。我们怎么求解这个位数呢?

方案一:逐位遍历

从低位向高位逐渐遍历即可,无需解释。当然也有很多种写法。这里提供一种。

int highestBit(int num) {

if (num == 0) return 0;

int pos = 0;

while (num > 1) {

num >>= 1;

pos++;

}

return pos;

}

方案二:部分打表

还有一个思路是空间换时间,对小范围的数据打表。假如我们首先计算出 lookup[256] 表示 0-255各自的最高位位置。由于 int 可以划分成8位为一块进行处理,我们先检查高16位是否有值,若有则只考虑高 16 位,否则只考虑低 16 位。同理再划分一次,我们则可以将范围缩小到 8 位,调用计算好的结果即可。

const int lookup[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 highestBit(int num) {

if (num == 0) return 0;

int pos = 0;

if (num & 0xFFFF0000) { pos += 16; num >>= 16; }

if (num & 0xFF00) { pos += 8; num >>= 8; }

return pos + lookup[num];

}

方案三:内置函数

在 C+ 中,GCC 和 Clang 编译器提供了一个内置函数 __builtin_clz,用于计算一个整数的前导零的数量。结合这个函数,可以快速找到一个整数的最高位1的位置。

#include // for CHAR_BIT

int highestBit(int num) {

if (num == 0) return 0;

return sizeof(num) * CHAR_BIT - 1 - __builtin_clz(num);

}

__builtin_clz(num):返回整数 num 的前导零的数量。sizeof(num) * CHAR_BIT:表示整数 num 的总位数。例如,对于32位整数,这个值是32。相减再减一就是正确答案。

使用 __builtin_clz 的效率通常非常高,这是因为它通常会被编译器翻译成一条高效的汇编指令。例如,在x86架构上,它通常被翻译成一条BSR(Bit Scan Reverse)或LZCNT(Leading Zero Count)指令,这些指令在硬件级别上非常高效。

大多数现代CPU都支持相关指令,在其他编译器(如MSVC)上可能需要不同的方法。可自行查阅。

注意处理负数

由于补码的性质,负数不存在最高位1。如果一定要定义一个,那么就是第31位(即表示符号的最高位),上面的函数均没有考虑负数情况,请多加注意。

🎊 相关推荐

iPhoneX性能测评(综合评估iPhoneX的性能表现,一探全新体验)
独家冠名赞助一场春晚要花多少钱?
365bet线上

独家冠名赞助一场春晚要花多少钱?

📅 11-29 👀 4488
王者荣耀大乔传送技巧有什么
365bet线上

王者荣耀大乔传送技巧有什么

📅 09-22 👀 4432