我需要将两个变量合并为一个,如下例所示:
x = 0b110101
y = 0b10011
merged(x,y) -> 0b11010111001
merged(y,x) -> 0b10011101011
因此,y
被颠倒并连接到x
而没有不必要的零(结果的最后一位总是1)
换句话说:merged(abcdefg, hijklm)
产生abcdefgmlkjih
,其中a
和h
是1
在C语言中最有效的方法是什么
编辑:效率最高=最快,sizeof(x)
= sizeof(y)
= 1
,CHAR_BIT
= 8
EDIT2:由于问题已搁置,我将在此处发布摘要: 进一步的限制和更多细节:
目标语言:支持64位操作的C
对于这个确切的问题,最快的方法是在注释中建议使用256个元素的查找表,该表返回高位N
的索引和第二个参数的取反值,因此我们可以将第一个参数向左移动N
,然后使用第二个参数的取反值按位执行or
。
如果某人需要良好的性能来处理大于8位的参数(不可使用查找表),则可以:
使用de Bruijn算法查找高位索引。 32位示例:
uint32_t msbDeBruijn32( uint32_t v )
{
static const int MultiplyDeBruijnBitPosition[32] =
{
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};
v |= v >> 1; // first round down to one less than a power of 2
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
return MultiplyDeBruijnBitPosition[( uint32_t )( v * 0x07C4ACDDU ) >> 27];
}
取自这个问题: Find most significant bit (left-most) that is set in a bit array
使用此位旋转hack来反转第二个参数的字节(一一字节)
unsigned char b; // reverse this (8-bit) byte
b = (b * 0x0202020202ULL & 0x010884422010ULL) % 1023;
从这里获取:http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious
因此,现在可以关闭/删除该问题
答案 0 :(得分:2)
这应该可以在C ++和C中达到目的:
unsigned int merged(unsigned char a, unsigned char b) {
unsigned int r = a;
for (; b; b>>=1)
r = (r<<1)|(b&1);
return r;
}
我认为没有比这更有效的方法了。这里是online demo。
这是通过从第一个参数开始构建结果来实现的:
r is 0b110101;
然后使用left-shifts r,即使用您的术语,例如在r的最低端连接一个0:
0b110101 << 1 is 0b1101010;
同时我们用bitwise and得到b的最低位,然后使用bitwise or将r的最低位设置为相同的值:
0b10011 & 1 is 0b00001
so (0b110101 << 1)|(0b10011 & 1) is 0b1101011;
然后我们右移b以相同的方式处理下一个最低位:
0b10011 >> 1 is 0b1001;
只要b中还有剩余位。
您必须小心使用的类型,以避免溢出的风险。因此,对于2 unsigned char
作为输入,您可以使用unsigned int
作为输出。
请注意,如果向左移动会导致符号位发生变化,则使用带符号的整数会带来风险。这就是unsigned
在这里很重要的原因。