高效的位运算

时间:2018-12-11 20:07:52

标签: c++ bit-manipulation

在C ++中,我想将3个无符号变量的位编码为1。更准确地说,当三个变量为:

A: a3 a2 a1 a0
B: b3 b2 b1 b0
C: c3 c2 c1 c0

然后输出变量应包含以下三元组:

D: a3 b3 c3   a2 b2 c2   a1 b1 c1   a0 b0 c0

我们假设输出变量对于所有使用的位都足够大。我想出了

unsigned long long result(0);
unsigned a,b,c; // Some numbers to be encoded
for(int level=0;level<numLevels;++level)
{
    int q(1<<level); // SearchBit q: 1<<level
    int baseShift((3*level)-level); // 0,2,4,6
    result|=(   ((a&q)<<(baseShift+2)) | ((b&q)<<(baseShift+1)) | ((c&q)<<(baseShift)) );
}

...并且可以正常工作。但是我想知道是否有一种解决方案不需要循环遍历所有位的循环。

1 个答案:

答案 0 :(得分:2)

定义一个表,将全部或部分位映射到它们的最终位置。适当地移动值。

unsigned long long encoder(unsigned a, unsigned b, unsigned c) {
    static unsigned const encoding[16] = {
        0b0000000000,
        0b0000000001,
        0b0000001000,
        0b0000001001,
        0b0001000000,
        0b0001000001,
        0b0001001000,
        0b0001001001,
        0b1000000000,
        0b1000000001,
        0b1000001000,
        0b1000001001,
        0b1001000000,
        0b1001000001,
        0b1001001000,
        0b1001001001,
    };

    unsigned long long result(0);

    int shift = 0;
    do {
        result += ((encoding[a & 0xF] << 2) | (encoding[b & 0xF] << 1) | encoding[c & 0xF]) << shift;
        shift += 12;
        a >>= 4;
        b >>= 4;
        c >>= 4;
    } while (a || b || c);
    return result;
}

encoding定义了一个表,用于将4位映射到它们的编码位置。它直接用于c,并为ba移位了1或2位。如果要处理的位多于4位,则源值中的后4位将向左偏移12位。继续执行此操作,直到处理完所有非零位为止。

这可以使用while循环而不是do/while,但是除非大多数编码都为零,否则在启动之前检查零是没有用的。

如果您经常使用4位以上,则可以扩展编码表,并对循环进行适当的更改以一次处理4位以上。