如何测试所有位是否已设置或未设置?

问题描述 投票:0回答:4

使用按位运算符如何测试整数的 n 个最低有效位是否全部设置或全部未设置。

例如

if n = 3
我只关心 3 个最低有效位,并且测试应该对于 0 和 7 返回 true,对于 0 到 7 之间的所有其他值返回 false。

当然我可以做

if x = 0 or x = 7
,但我更喜欢使用按位运算符。

如果可以调整该技术以考虑掩码定义的所有位,则会加分。

澄清:

如果我想测试是否设置了位一或位二,我可以做

if ((x & 1 != 0) && (x & 2 != 0))
。但我可以做到“更有效率”
if ((x & 3) != 0)

我正在尝试找到这样的“黑客”来回答这个问题“x 中与此掩码匹配的所有位都是全部设置还是全部未设置?”

最简单的方法是

if ((x & mask) == 0 || (x & mask) == mask)
。我想找到一种方法在一次测试中做到这一点,而无需 ||操作员。

c++ c bit-manipulation
4个回答
14
投票

使用按位运算符如何测试整数的 n 个最低有效位是否全部为集合或全部不是集合。

要获取最后

n
有效位的掩码,那就是

(1ULL << n) - 1

所以简单的测试是:

bool test_all_or_none(uint64_t val, uint64_t n)
{
    uint64_t mask = (1ULL << n) - 1;
    val &= mask;
    return val == mask || val == 0;
}

如果你想避免

||
,我们就必须利用整数溢出。对于我们想要的情况,在
&
之后,
val
0
或(假设 n == 8)
0xff
。所以
val - 1
要么是
0xffffffffffffffff
要么
0xfe
。失败原因是
1
0xfe
,变成
0
0xfd
。因此成功案例至少被称为
0xfe
,即
mask - 1
:

bool test_all_or_none(uint64_t val, uint64_t n)
{
    uint64_t mask = (1ULL << n) - 1;
    val &= mask;
    return (val - 1) >= (mask - 1);
}

我们还可以通过加 1 而不是减 1 来进行测试,这可能是最好的解决方案(这里,一旦我们向

val
添加 1,对于我们的成功案例,
val & mask
应该变成
0
1
):

bool test_all_or_none(uint64_t val, uint64_t n)
{
    uint64_t mask = (1ULL << n) - 1;
    return ((val + 1) & mask) <= 1;
}     

对于任意掩码,减法的工作原理与特定掩码情况相同:

0
翻转为最大可能值:

bool test_all_or_none(uint64_t val, uint64_t mask)
{
    return ((val & mask) - 1) >= (mask - 1);
}

4
投票

怎么样?

int mask = (1<<n)-1;
if ((x&mask)==mask || (x&mask)==0) { /*do whatever*/ }

唯一真正棘手的部分是掩码的计算。 它基本上只是将 1 移到

0b0...0100...0
,然后减去 1 得到
0b0...0011...1

也许你可以澄清一下你想要测试什么?


1
投票

这就是您想要在一个函数中执行的操作(未经测试,但您应该明白这一点)。如果最后 n 位未设置,则返回 0;如果全部设置,则返回 1;否则返回 -1。

int lastBitsSet(int num, int n){
    int mask = (1 << n) - 1; //n 1-s
    if (!(num & mask)) //we got all 0-s
        return 0;
    if (!(~num & mask)) //we got all 1-s
        return 1;
    else
        return -1;
}

0
投票

要测试是否全部未设置,您只需掩码您想要的位,然后只需与零进行比较即可。

当您通过反转输入来定义相反函数时,乐趣就开始了:)

//Test if the n least significant bits arent set:
char n_least_arent_set(unsigned int n, unsigned int value){
  unsigned int mask = pow(2, n) - 1; // e. g. 2^3 - 1 = b111
  int masked_value = value & mask;
  return masked_value == 0; // if all are zero, the mask operation returns a full-zero.      
}

//test if the n least significant bits are set:
char n_least_are_set(unsigned int n, unsigned int value){
  unsigned int rev_value = ~value;
  return n_least_arent_set(n, rev_value);    
}
© www.soinside.com 2019 - 2024. All rights reserved.