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

时间:2013-04-22 06:09:51

标签: c++

我想知道如何扭转像this这样的东西。那么mask auto mask = 1ULL << 20;如何从掩码中取出20

8 个答案:

答案 0 :(得分: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;
}

输出

20

我想,我找到了here

答案 1 :(得分: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;
}

或循环和转移:

#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;
}

答案 2 :(得分: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];
}

答案 3 :(得分:1)

一个简单的循环就可以了:

for (int bit = 0; bit < sizeof(mask) * 8; bit++)
{
    if ((1ULL << bit) & mask)
        std::cout << "Bit " << bit << " is set in the mask\n";
}

答案 4 :(得分:1)

选项1:迭代

while (mask && !(mask & 1)) { mask>>=1; count++; }

选项2:一次迭代多个位:

unsigned long long a=0xFFFFFFFFULL; int b=32;
while (mask>1) {
    if (!(mask & a)) { count+=b; mask>>=b; }
    b>>=1; mask>>=b;
}

选项3:将掩码转换为double或float并提取指数。

union { 
     struct {
        int mantissa:23;
        int exp:7;
        int sign:1;
     } s;
     float f;
} u = { (float) mask };

return u.s.exp + 1;

答案 5 :(得分:1)

//first if you want to make sure only 1 bit is "on" you can do that:
if ((mask & mask-1) != 0)
{
    //you have more than 1 bit "on", deal with it...
}

//finding which bit is "on" can be achieve in a loop
int count 0;
while (mask > 1)
{
    mask>>=1;
    count++;
}

//At this point count will have the required value (20 in your example)

答案 6 :(得分:0)

TMP解决方案如何:

#include <iostream>

template < unsigned long long MASK >
struct MaskIndex
{
    enum { i = MaskIndex < MASK / 2 >::i + 1 };
};

template <>
struct MaskIndex < 1 >
{
    enum { i = 0 };
};

int main()
{
    const unsigned long long mask = 1ULL << 20;
    std::cout << MaskIndex < mask >::i << std::endl;
    return ( 0 );
}

答案 7 :(得分:-1)

你可以试试这个..

if((1ULL<<20)&mask) {
        cout << "20th bit is set";
}