在C中找到最高位
时间:2020-03-05 18:50:26 来源:igfitidea点击:
我需要的是可以输入数字的东西,它将返回最高位。我敢肯定有一个简单的方法。下面是一个示例输出(左边是输入)
1 -> 1 2 -> 2 3 -> 2 4 -> 4 5 -> 4 6 -> 4 7 -> 4 8 -> 8 9 -> 8 ... 63 -> 32
解决方案
回答
不断删除低阶位的想法...
int highest_order_bit( int x ) { int y = x; do { x = y; y = x & (x-1); //remove low order bit } while( y != 0 ); return x; }
回答
这应该可以解决问题。
int hob (int num) { if (!num) return 0; int ret = 1; while (num >>= 1) ret <<= 1; return ret; }
滚刀(1234)返回1024
滚刀(1024)返回1024
滚刀(1023)返回512
回答
从黑客的喜悦:
int hibit(unsigned int n) { n |= (n >> 1); n |= (n >> 2); n |= (n >> 4); n |= (n >> 8); n |= (n >> 16); return n - (n >> 1); }
此版本适用于32位整数,但逻辑可以扩展到64位或者更高版本。
回答
linux内核具有许多这样的便捷位,它们以最有效的方式对许多体系结构进行了编码。我们可以在include / asm-generic / bitops / fls.h(和朋友)中找到通用版本,但如果速度至关重要,并且可移植性非常好,另请参见include / asm-x86 / bitops.h中的内联汇编定义。不是。
回答
一种快速的方法是通过查找表。对于32位输入和8位查找表,仅需要进行4次迭代:
int highest_order_bit(int x) { static const int msb_lut[256] = { 0, 0, 1, 1, 2, 2, 2, 2, // 0000_0000 - 0000_0111 3, 3, 3, 3, 3, 3, 3, 3, // 0000_1000 - 0000_1111 4, 4, 4, 4, 4, 4, 4, 4, // 0001_0000 - 0001_0111 4, 4, 4, 4, 4, 4, 4, 4, // 0001_1000 - 0001_1111 5, 5, 5, 5, 5, 5, 5, 5, // 0010_0000 - 0010_0111 5, 5, 5, 5, 5, 5, 5, 5, // 0010_1000 - 0010_1111 5, 5, 5, 5, 5, 5, 5, 5, // 0011_0000 - 0011_0111 5, 5, 5, 5, 5, 5, 5, 5, // 0011_1000 - 0011_1111 6, 6, 6, 6, 6, 6, 6, 6, // 0100_0000 - 0100_0111 6, 6, 6, 6, 6, 6, 6, 6, // 0100_1000 - 0100_1111 6, 6, 6, 6, 6, 6, 6, 6, // 0101_0000 - 0101_0111 6, 6, 6, 6, 6, 6, 6, 6, // 0101_1000 - 0101_1111 6, 6, 6, 6, 6, 6, 6, 6, // 0110_0000 - 0110_0111 6, 6, 6, 6, 6, 6, 6, 6, // 0110_1000 - 0110_1111 6, 6, 6, 6, 6, 6, 6, 6, // 0111_0000 - 0111_0111 6, 6, 6, 6, 6, 6, 6, 6, // 0111_1000 - 0111_1111 7, 7, 7, 7, 7, 7, 7, 7, // 1000_0000 - 1000_0111 7, 7, 7, 7, 7, 7, 7, 7, // 1000_1000 - 1000_1111 7, 7, 7, 7, 7, 7, 7, 7, // 1001_0000 - 1001_0111 7, 7, 7, 7, 7, 7, 7, 7, // 1001_1000 - 1001_1111 7, 7, 7, 7, 7, 7, 7, 7, // 1010_0000 - 1010_0111 7, 7, 7, 7, 7, 7, 7, 7, // 1010_1000 - 1010_1111 7, 7, 7, 7, 7, 7, 7, 7, // 1011_0000 - 1011_0111 7, 7, 7, 7, 7, 7, 7, 7, // 1011_1000 - 1011_1111 7, 7, 7, 7, 7, 7, 7, 7, // 1100_0000 - 1100_0111 7, 7, 7, 7, 7, 7, 7, 7, // 1100_1000 - 1100_1111 7, 7, 7, 7, 7, 7, 7, 7, // 1101_0000 - 1101_0111 7, 7, 7, 7, 7, 7, 7, 7, // 1101_1000 - 1101_1111 7, 7, 7, 7, 7, 7, 7, 7, // 1110_0000 - 1110_0111 7, 7, 7, 7, 7, 7, 7, 7, // 1110_1000 - 1110_1111 7, 7, 7, 7, 7, 7, 7, 7, // 1111_0000 - 1111_0111 7, 7, 7, 7, 7, 7, 7, 7, // 1111_1000 - 1111_1111 }; int byte; int byte_cnt; for (byte_cnt = 3; byte_cnt >= 0; byte_cnt--) { byte = (x >> (byte_cnt * 8)) & 0xff; if (byte != 0) { return msb_lut[byte] + (byte_cnt * 8); } } return -1; }
回答
像混淆代码?试试这个:
1 <<(int)log2(x)
回答
这可以通过现有的库调用轻松解决。
int highestBit(int v){ return fls(v) << 1; }
Linux手册页提供了有关此功能及其其他输入类型的更多详细信息。