我的问题如下:我有一个值x
和一个模式p
两个相同大小的变量。目标是遍历由 屏蔽的x的所有位模式。
实施例:
如果我们有p = 1001
,我们希望找到0000
,0001
,1000
和1001
- 不一定按此顺序。
C99中的标准实现(返回值指定我们是否已经返回所有值):
static bool next(size_t val, size_t mask, size_t *out) {
if (val == mask) {
return false;
}
size_t current = val & mask;
size_t inc = 1;
size_t new_val = current + inc;
while ((new_val & mask) <= current) {
inc++;
new_val = current + inc;
}
*out = new_val;
return true;
}
我认为应该有一些技巧可以提高效率,但我似乎无法找到任何重大改进(除了计算掩码的尾随零并适当设置inc的起始值,这不是'很多改进)。
编辑:同样重要的是,对于每个生成的值,会产生大量额外的工作,这意味着大量的重复是不可能的(一些重复,即使不可识别也没关系,没有任何重复对完成的工作产生副作用,这只是一个减速)。
答案 0 :(得分:15)
这会以相反的顺序生成所有位模式(val
的初始值应等于mask
):
static bool next(size_t val, size_t mask, size_t *out) {
if (val == 0) {
return false;
}
*out = (val - 1) & mask;
return true;
}
这个(稍微不那么明显的代码)按直接顺序生成所有位模式(val
的初始值应为零):
static bool next(size_t val, size_t mask, size_t *out) {
if (val == mask) {
return false;
}
*out = (val - mask) & mask;
return true;
}
答案 1 :(得分:1)
从您的示例中,看起来这个伪代码可以解决这个问题:
current = p // set up current
getNotMasked(p, 0) // initial call
bitString current
getNotMasked(int pos)
if (pos == current.length)
print(current)
return
if (current[pos] == 1)
current[pos] = 0
getNotMasked(pos+1)
current[pos] = 1
getNotMasked(pos+1)
else
getNotMasked(pos+1)
从此处生成C代码应该不难 - 将bitString
替换为int
,将[pos]
替换为& 1 << pos
或类似。
答案 2 :(得分:0)
最佳方式如下:
这当然假设进行改组是合理有效的,否则根据模式中总的位数,从0到最大可能值计数就更容易强制它。 ,并在每个计数应用模式。但是,检测重复项可能有点贵。
对于p = 9
(二进制1001 2 ),只设置了两个位,因此我们知道要生成2个 2 = 4个值。 / p>
从右侧扫描模式为1位,我们可以形成以下“混洗表”:
因此,我们可以从0到3进行计数,并根据表格重新排列每个值: