递增 'masked' 位集
Incrementing 'masked' bitsets
我目前正在编写树枚举器,但遇到了以下问题:
我正在查看掩码位集,即设置位是掩码子集的位集,即 0000101
和掩码 1010101
。我想要完成的是增加位集,但仅限于屏蔽位。在此示例中,结果将是 0010000
。为了让它更清楚一点,只提取掩码位,即 0011
,将它们递增到 0100
并再次将它们分配给掩码位,得到 0010000
.
除了使用位扫描和前缀掩码的组合手动执行操作之外,是否有人看到了执行此操作的有效方法?
只需用 1 填充非掩码位,以便它们传播进位:
// increments x on bits belonging to mask
x = ((x | ~mask) + 1) & mask;
虽然与公认的答案相比不够直观,但只需 3 个步骤即可完成:
x = -(x ^ mask) & mask;
这可以按照zch的建议进行验证:
-(x ^ mask)
= ~(x ^ mask) + 1 // assuming 2's complement
= (x ^ ~mask) + 1
= (x | ~mask) + 1 // since x and ~mask have disjoint set bits
然后它就等同于接受的答案。
如果迭代的顺序不是那么重要,一个自减操作就可以满足你的需要,可以只用两个操作:
让我们从
开始
x = mask
并使用
获取之前的值
x = (x - 1) & mask
x - 1
部分将最后一个非零位更改为零,并将所有低位设置为 1。然后& mask
部分只留下其中的掩码位。
我目前正在编写树枚举器,但遇到了以下问题:
我正在查看掩码位集,即设置位是掩码子集的位集,即 0000101
和掩码 1010101
。我想要完成的是增加位集,但仅限于屏蔽位。在此示例中,结果将是 0010000
。为了让它更清楚一点,只提取掩码位,即 0011
,将它们递增到 0100
并再次将它们分配给掩码位,得到 0010000
.
除了使用位扫描和前缀掩码的组合手动执行操作之外,是否有人看到了执行此操作的有效方法?
只需用 1 填充非掩码位,以便它们传播进位:
// increments x on bits belonging to mask
x = ((x | ~mask) + 1) & mask;
虽然与公认的答案相比不够直观,但只需 3 个步骤即可完成:
x = -(x ^ mask) & mask;
这可以按照zch的建议进行验证:
-(x ^ mask)
= ~(x ^ mask) + 1 // assuming 2's complement
= (x ^ ~mask) + 1
= (x | ~mask) + 1 // since x and ~mask have disjoint set bits
然后它就等同于接受的答案。
如果迭代的顺序不是那么重要,一个自减操作就可以满足你的需要,可以只用两个操作:
让我们从
开始x = mask
并使用
获取之前的值x = (x - 1) & mask
x - 1
部分将最后一个非零位更改为零,并将所有低位设置为 1。然后& mask
部分只留下其中的掩码位。