找到C中的最高位

Har*_*mbe 42 c

我所追求的是我可以输入一个数字的东西,它将返回最高位.我确信这有一个简单的方法.下面是一个示例输出(左边是输入)

1 -> 1
2 -> 2
3 -> 2
4 -> 4
5 -> 4
6 -> 4
7 -> 4
8 -> 8
9 -> 8
...
63 -> 32

eri*_*son 83

来自Hacker's Delight:

int hibit(unsigned int n) {
    n |= (n >>  1);
    n |= (n >>  2);
    n |= (n >>  4);
    n |= (n >>  8);
    n |= (n >> 16);
    return n - (n >> 1);
}
Run Code Online (Sandbox Code Playgroud)

此版本用于32位整数,但逻辑可以扩展到64位或更高.

  • 更少的晶体管,更高的效率,更少的热量,更多的循环:) (3认同)
  • @alveko虽然XOR可以比晶体管/门级的减法更快地实现,但它们在大多数现代CPU上需要相同的时钟周期数 (2认同)
  • 为了直观起见,此操作将MSB向右“传播”,以便0b100010变为0b111111,然后向右移0b011111并减去,得出0b100000。 (2认同)

Fab*_*ian 39

fls最底层的是许多架构的硬件指令.我怀疑这可能是最简单,最快速的方式.

1<<(fls(input)-1)
Run Code Online (Sandbox Code Playgroud)

  • 显然是最好的答案。我不知道为什么所有这些网站都像是点点滴滴的骇客,而这些网站如此专注​​于减少针对此类问题的操作次数,甚至没有提及这一点。 (2认同)
  • @jww是正确的。`fls(0)`-&gt; 0,未定义`&lt;&lt;`的rhs为负。在我的辩护中,问题空间中未提及;-) (2认同)

Kyl*_*nin 30

这应该可以解决问题.

int hob (int num)
{
    if (!num)
        return 0;

    int ret = 1;

    while (num >>= 1)
        ret <<= 1;

    return ret;
}
Run Code Online (Sandbox Code Playgroud)

滚刀(1234)返回1024
滚刀(1024)返回1024
滚刀(1023)返回512

  • 我的回答更好.没有循环! (3认同)
  • 对于GCC,更好的函数是__builtin_clz(v) - 它返回前导(二进制)零的数量,因此您可以通过32-clz(num)(或64-clzll(num)获得最高位位置) 64位) (3认同)

dmi*_*gov 26

像混淆代码?试试这个:

1 <<(int)log2(x)

  • 如果你想在FPU上关闭作业,当然.:) (10认同)
  • 在数学上是正确的,但这可能比按位运算慢得多. (9认同)
  • 如果你把它加到第一位,那么数字的指数部分就会告诉你顺序. (4认同)
  • 注意数字表示形式。此配方适用于正32位整数。但是`std :: log2()`为否定参数返回`nan`,而`int(nan)`的计算结果为'0x80000000`,这是最大的负整数。对于g ++ 7.3,可以观察到这一点,但恐怕这是不可移植的。下一个问题是舍入错误。当您输入64位数字时,一切正常,直到2 ^ {48} -1。但是对于2 ^ {49} -1,配方返回2 ^ {49}。 (2认同)

Kea*_*ean 9

这个聚会有点晚了,但我找到的最简单的解决方案,考虑到现代 GCC 作为编译器很简单:

static inline int_t get_msb32 (register unsigned int val)
{
  return 32 - __builtin_clz(val);
}

static inline int get_msb64 (register unsigned long long val)
{
  return 64 - __builtin_clzll(val);
}
Run Code Online (Sandbox Code Playgroud)

它甚至相对便携(至少它可以在任何 GCC 平台上运行)。


nlu*_*oni 6

想到不断删除低位...

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;
}
Run Code Online (Sandbox Code Playgroud)


小智 5

linux 内核有许多这样的方便的位元,以最有效的方式为许多体系结构编码。您可以在include/asm-generic/bitops/fls.h(和朋友)中找到通用版本,但如果速度至关重要,并且可移植性很重要,请参阅include/asm-x86/bitops.h以获取使用内联汇编的定义不是。


dha*_*rga 5

现有的库调用可以很容易地解决这个问题.

int highestBit(int v){
  return fls(v) << 1;
}
Run Code Online (Sandbox Code Playgroud)

Linux手册页提供了有关此函数的更多详细信息以及其他输入类型的对应函数.

  • 实际上,ffs返回最低位. (4认同)
  • @Ragnar,如果您采用这种方式,请使用(CHAR_BIT * sizeof(long long)-__builtin_clzll(v)`,但我不认为此公式很容易携带,因此不需要。 (2认同)