8

我想知道如何扭转这样的事情。那么有一个如何摆脱面具的mask地方呢?auto mask = 1ULL << 20;20

4

8 回答 8

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

我想,我在这里找到了。

于 2013-04-22T06:16:57.927 回答
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;
}
于 2013-04-22T06:13:52.090 回答
5

If it's a 64-bit mask, you can compute it modulo 67 and do a table lookup.

To wit:

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];
}
于 2013-04-22T06:49:35.610 回答
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)
于 2013-04-22T06:22:51.157 回答
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:将掩码转换为双精度或浮点数并提取指数。

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

return u.s.exp + 1;
于 2013-04-22T06:16:29.077 回答
1

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

for (int bit = 0; bit < sizeof(mask) * 8; bit++)
{
    if ((1ULL << bit) & mask)
        std::cout << "Bit " << bit << " is set in the mask\n";
}
于 2013-04-22T06:14:20.320 回答
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 );
}
于 2013-04-22T06:45:25.893 回答
-1

你可以试试这个。。

if((1ULL<<20)&mask) {
        cout << "20th bit is set";
}
于 2013-04-22T06:17:27.477 回答