如何从无符号长长的面具中获取数字?

myW*_*SON 8 c++

我不知道如何扭转像这样.有这么一个mask地方auto mask = 1ULL << 20;如何获得20来自屏蔽掉?

mas*_*oud 11

无环路

很多年前,当我为国际象棋引擎编写一个有点算术运算时,我发现了一个快速实现,它对你的需求很有用,它是无循环的.此方法将1从右到左(最低有效位)返回第一个位的位置:

inline unsigned int lsb(unsigned long long value)
{
    if (!value)
        return -1;

    value &= -value;
    unsigned int lsb = (unsigned) value | (unsigned) (value >> 32);
    return (((((((((((unsigned) (value >> 32) != 0) << 1)
            + ((lsb & 0xffff0000) != 0)) << 1)
            + ((lsb & 0xff00ff00) != 0)) << 1)
            + ((lsb & 0xf0f0f0f0) != 0)) << 1)
            + ((lsb & 0xcccccccc) != 0)) << 1)
            + ((lsb & 0xaaaaaaaa) != 0);
}

int main()
{
    unsigned long long x = 1ULL<<20;
    cout << lsb(x) << endl;
}
Run Code Online (Sandbox Code Playgroud)

产量

20
Run Code Online (Sandbox Code Playgroud)

我想,我在这里找到了它.

  • @MSalters代码不是很明显应该始终有注释.这段代码并不明显.是的,你会在一段时间后理解它,但你应该立即理解它.我必须先用数字来测试它才能理解`&= -value`和`lsb =`.命名变量`value`总是有点问题. (2认同)

per*_*eal 6

使用日志:

#include <iostream>
#include <cmath>
int main() {
    auto mask = 1ULL << 20; 
    std::cout << log2(mask) << std::endl;
    // edit out: std::cout << log(mask) / log(2) << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

或循环和移位:

#include <iostream>
int main() {
    auto mask = 1ULL << 20; 
    for (unsigned int c = 0; c < sizeof(mask) * 8 && mask; c++) {
        mask >>= 1;
        if (mask == 0)
            std::cout << c << std::endl;
    }   
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 我认为,与循环相比,2个日志调用会有点慢 (3认同)

tmy*_*ebu 5

如果它是64位掩码,您可以将其计算为67并进行表查找.

以机智:

static int table[67] = {
  -1, 0, 1,39, 2,15,40,23, 3,12,
  16,59,41,19,24,54, 4,-1,13,10,
  17,62,60,28,42,30,20,51,25,44,
  55,47, 5,32,-1,38,14,22,11,58,
  18,53,63, 9,61,27,29,50,43,46,
  31,37,21,57,52, 8,26,49,45,36,
  56, 7,48,35, 6,34,33};

int unmask(unsigned long long ull) {
 return table[ull % 67];
}
Run Code Online (Sandbox Code Playgroud)