生成给定掩码的所有位模式

时间:2013-02-03 11:33:06

标签: c algorithm optimization bit-manipulation

我的问题如下:我有一个值x和一个模式p两个相同大小的变量。目标是遍历由 屏蔽的x的所有位模式。

实施例: 如果我们有p = 1001,我们希望找到0000000110001001 - 不一定按此顺序。

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的起始值,这不是'很多改进)。

编辑:同样重要的是,对于每个生成的值,会产生大量额外的工作,这意味着大量的重复是不可能的(一些重复,即使不可识别也没关系,没有任何重复对完成的工作产生副作用,这只是一个减速)。

3 个答案:

答案 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)

最佳方式如下:

  1. 计算掩码中的设置位数,p
  2. 找出一种方法,将位从“标准化”二进制值混洗到由模式决定的位置
  3. 通过0..2 p -1
  4. 计数
  5. 为每个值shuffle生成模式兼容值
  6. 这当然假设进行改组是合理有效的,否则根据模式中的位数,从0到最大可能值计数就更容易强制它。 ,并在每个计数应用模式。但是,检测重复项可能有点贵。

    对于p = 9(二进制1001 2 ),只设置了两个位,因此我们知道要生成2个 2 = 4个值。 / p>

    从右侧扫描模式为1位,我们可以形成以下“混洗表”:

    • 从位0
    • 复制位0
    • 从位1
    • 复制位3

    因此,我们可以从0到3进行计数,并根据表格重新排列每个值:

    • 00 2 给出输出0000 2
    • 01 2 给出输出0001 2
    • 10 2 给出输出1000 2
    • 11 2 给出输出1001 2