如何有效地翻转 C++ 中数字/位集的一部分?

问题描述

考虑我有一个长度为 6 的数字 100101。我希望从位置 2 开始翻转位到 5,所以我的答案是 111011。我知道我可以在循环中翻转单个位。但是有没有一种没有 for 循环的有效方法呢?

解决方法

如果我理解正确,请尝试

namespace {
unsigned flip(unsigned a)
{
   return a ^ 0b011110u;
}
}  // namespace

只需将常量调整为您想要翻转的实际位,将它们作为常量中的 1 即可。

另一方面,如果你只需要更新一个单独的变量,你也可以使用

unsigned value = 0b100101u;
value ^= 0b011110u;
assert(value == 0b111011u);

编辑 使用 std::bitset<6u> 和 C++98 也是如此:

#include <bitset>
#include <cassert>

int main()
{
   std::bitset<6u> const kFlipBit2to6WithXor(0x1Eu);  // aka 0b011110u
   std::bitset<6u> number(0x25u);                     // aka 0b100101u
   number ^= kFlipBit2to6WithXor;
   assert(number.to_ulong() == 0x3Bu);                // aka 0b111011u
   return 0;
}
,

0b11110b10000-1

constexpr unsigned low_mask(unsigned x){
  return (1u<<x)-1;
}

0b11000b1111-0b11

constexpr unsigned mask(unsigned width,unsigned offset){
  return low_mask(width+offset)-low_mask(offset);
}

然后使用异或来翻转位。

unsigned result = 0b100001 ^ mask(4,2);