有没有一种快速的方法来获取二进制值中等于 1 的位的索引?

Is there a fast way to get the index of bit which equal 1 in a binary value?

我想得到二进制格式等于1的索引,现在我使用这样的代码:

inline static uint8_t the_index(uint32_t val){
  return uint8_t(log(val & ((~val) + 1))/log(2));
}

我想知道是否有其他方法可以达到同样的目的?有没有可能用位运算来解决这个问题?

我这样做是为了迭代一个值并构建一些取决于迭代位置的操作,伪代码如下:

 while (temp) {
            auto cur_index = the_index(temp);
            auto window = ((1 << i) - 1) << cur_index;
            if (((temp & window) ^ window) == 0) {
              //....do something
            }
            temp &= temp - 1;
        }

如果问题是关于查找值中单个位的索引,比如 uint32_t x = b000010000;,一个快速的方法是

auto index = builtin_popcount(x - 1);

// example: b000010000 - 1
//          b000001111
// popcount(b000001111) == 4

在 arm64 架构中,最好的方法是使用 count_leading_zero(x) instruction/operation,因为通用寄存器缺乏快速弹出计数。

更仔细地阅读 OP,不能保证 x 只设置了一位——问题似乎是找到最低有效位集的索引。可以用

隔离
 x = temp & (0-temp);

有一个标准函数:

auto cur_index = std::countr_zero(temp);

在我的系统上,编译为:

xor     eax, eax
tzcnt   eax, edi

请注意,无论输入是否恰好有一个设置位,此函数都会成功地从右到第一个位计算零位。

我建议您使用 __builtin_ctzl : Returns x 中尾随 0 位的数量,从最低有效位开始。 (警告:如果 x 为 0,则结​​果未定义)。

示例:__builtin_ctzl(0x10) = 4,__builtin_ctzl(0x20) = 5

对于你的情况,你可以像这样使用它:

unsigned index;
do {
    index = temp ? __builtin_ctzl(temp) : 0;
    ... //do your stuff
    temp -= pow(2, index);
} while (index);