在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)) );
}
...并且可以正常工作。但是我想知道是否有一种解决方案不需要循环遍历所有位的循环。
答案 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
,并为b
和a
移位了1或2位。如果要处理的位多于4位,则源值中的后4位将向左偏移12位。继续执行此操作,直到处理完所有非零位为止。
这可以使用while
循环而不是do/while
,但是除非大多数编码都为零,否则在启动之前检查零是没有用的。
如果您经常使用4位以上,则可以扩展编码表,并对循环进行适当的更改以一次处理4位以上。