如何测试所有位是否置位或所有位都不是?

时间:2015-02-08 04:44:07

标签: c++ c bit-manipulation

使用按位运算符如何测试整数的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)。我想在没有||的单个测试中找到一种方法操作

4 个答案:

答案 0 :(得分:10)

  

使用按位运算符如何测试整数的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;
}

如果你想避开||,我们必须利用整数溢出。对于我们想要的情况,在&之后,val0或(假设n == 8)0xff。因此val - 1可以是0xffffffffffffffff0xfe。失败原因是10xfe,后者变为00xfd。因此,成功案例至少调用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来进行测试,这可能是最佳解决方案(此处我们将一个添加到valval & mask应该变为0或{{ 1}}对于我们的成功案例):

1

对于任意掩码,减法方法的作用与它对特定掩码大小写有效的原因相同:bool test_all_or_none(uint64_t val, uint64_t n) { uint64_t mask = (1ULL << n) - 1; return ((val + 1) & mask) <= 1; } 翻转为最大可能值:

0

答案 1 :(得分:3)

怎么样?

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

唯一真正棘手的部分是掩码的计算。它基本上只是将1移动到0b0...0100...0,然后减去1以使其成为0b0...0011...1

也许你可以澄清你想要的测试内容?

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

答案 3 :(得分:0)

要测试是否所有都没有设置,你只需要屏蔽所需的位,然后你只需要比较为零。

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

//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);    
}