我目前正在编写一种树形枚举器,在其中遇到了以下问题:
我正在研究掩码位集,即只有在掩码内的位才是置位的位集,例如用掩码 1010101
来描述 0000101
。我想要实现的是递增位集,但仅限于掩码内的位。在这个例子中,结果将会是 0010000
。为了更清晰地表达,仅提取掩码内的位,即 0011
,将其递增至 0100
并再次分布到掩码内的位,得到 0010000
。
有没有人知道一种高效的方法来做到这一点,而不是手动使用位扫描和前缀掩码的组合来实现操作?
我目前正在编写一种树形枚举器,在其中遇到了以下问题:
我正在研究掩码位集,即只有在掩码内的位才是置位的位集,例如用掩码 1010101
来描述 0000101
。我想要实现的是递增位集,但仅限于掩码内的位。在这个例子中,结果将会是 0010000
。为了更清晰地表达,仅提取掩码内的位,即 0011
,将其递增至 0100
并再次分布到掩码内的位,得到 0010000
。
有没有人知道一种高效的方法来做到这一点,而不是手动使用位扫描和前缀掩码的组合来实现操作?
将非掩码位填充为1,以便它们传递进位:
// increments x on bits belonging to mask
x = ((x | ~mask) + 1) & mask;
虽然与被接受的答案相比不太直观,但这种方法仅需要三个步骤:
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 | ~mask) + 1
,那么我认为您的验证会简单得多,然后可以参考我的答案。 - zch如果迭代顺序不重要且递减操作能够满足您的需求,则可以仅使用两个操作:
首先执行
x = mask
然后通过以下方式获取上一个值
x = (x - 1) & mask
x - 1
部分将最后一个非零位更改为零,并将所有低位设置为1。然后 & mask
部分只保留其中的掩码位。
x = (x & ~mask) | (((x | ~mask) + 1) & mask);
。 - TripeHound0101101
(例如在非掩码位中为.1.1.0.
,在“计数器”中为0.0.1.1
),他们是否需要0111000
(一个新的“计数器”为0.1.0.0
,同时保留.1.1.0.
)或者只有0010000
是可以接受的。这个答案(可能还有其他答案,但我没有检查)给出了后者;如果需要前者,我的版本应该给出前者。 - TripeHound