完美实现按位NOT(〜)运算符(翻转位)

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

最近,我正在做一些与位操作有关的事情。到目前为止,我已经尝试了许多位操作。但是我只能进行一次手术。

假设我的整数n = 5;二进制(101),现在我想对这个int执行按位NOT运算,我认为结果是(010),但是结果是-6。

但是当我尝试n =〜(-n)时,结果为4(尽管仍然没有得到正确的输出)。请告诉我为什么显示这种行为是因为我的int不是未签名的。另外,请告诉我实现此操作的理想方法,以便获得正确的输出。我的主要动机是正确翻转位。

谢谢

c++ c bit-manipulation bitwise-operators bit
2个回答
2
投票

您可能想要这个:

// assuming n is a 32 bit int
n = 5;          // n = 00000000000000000000000000000101
n = ~n;         // n = 11111111111111111111111111111010
n = n & 0x7;    // n = 00000000000000000000000000000010

使用&运算符(按位和)可屏蔽n的第3至31位

您可以选择将最后两个语句合而为一:

n = ~n & 0x7;

2
投票

int具有多个树位,因此您必须掩盖像这样的按位求反的结果:

int flip(int n) {
    // bitwise AND with 0b111 = 7, this will clear all but the last 3 bits
    return ~n & 0b111;
}

得到-6的原因是,int通常用二进制补码表示,其中-6是所有1位,但以010结尾。您必须删除这些前导1位才能获得正确的结果。

通常,我建议不要对带符号的数字使用按位运算,而应执行以下操作:

unsigned flip(unsigned n) {
    return ~n & 0b111;
}

// this version works with any number of bits, not just 3
unsigned flip(unsigned n, unsigned bits) {
    unsigned mask = (1 << bits) - 1;
    return ~n & mask;
}

如果您不知道数字有多少位,则必须首先找到最高有效位。以最幼稚的方式,可以这样做:

unsigned log2(unsigned val)
{
    unsigned result = 0;
    while (val >>= 1) {
        ++result;
    }
    return result;
}

unsigned variable_flip(unsigned n) {
    return flip(n, log2(n));
}

您可以找到更有效的解决方案here

例如:

unsigned log2_debruijn(uint32_t val) {
    static const unsigned MultiplyDeBruijnBitPosition[32] = {0, 9,  1,  10, 13, 21, 2,  29, 11, 14, 16, 18, 22, 25, 3, 30,
                                                          8, 12, 20, 28, 15, 17, 24, 7,  19, 27, 23, 6,  26, 5,  4, 31};

    // first round down to one less than a power of 2
    // this step is not necessary if val is a power of 2
    val |= val >> 1;
    val |= val >> 2;
    val |= val >> 4;
    val |= val >> 8;
    val |= val >> 16;

    return MultiplyDeBruijnBitPosition[(val * uint32_t{0x07C4ACDD}) >> 27];
}
© www.soinside.com 2019 - 2024. All rights reserved.