快速位串联反转参数之一

时间:2018-09-25 20:19:33

标签: c bit-manipulation

我需要将两个变量合并为一个,如下例所示:

x = 0b110101
y = 0b10011

merged(x,y) -> 0b11010111001
merged(y,x) -> 0b10011101011

因此,y被颠倒并连接到x而没有不必要的零(结果的最后一位总是1)

换句话说:merged(abcdefg, hijklm)产生abcdefgmlkjih,其中ah1

在C语言中最有效的方法是什么

编辑:效率最高=最快,sizeof(x) = sizeof(y) = 1CHAR_BIT = 8

EDIT2:由于问题已搁置,我将在此处发布摘要: 进一步的限制和更多细节:

目标语言:支持64位操作的C

对于这个确切的问题,最快的方法是在注释中建议使用256个元素的查找表,该表返回高位N的索引和第二个参数的取反值,因此我们可以将第一个参数向左移动N,然后使用第二个参数的取反值按位执行or

如果某人需要良好的性能来处理大于8位的参数(不可使用查找表),则可以:

  1. 使用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

  1. 使用此位旋转hack来反转第二个参数的字节(一一字节)

    unsigned char b; // reverse this (8-bit) byte    
    b = (b * 0x0202020202ULL & 0x010884422010ULL) % 1023;  
    

从这里获取:http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious

因此,现在可以关闭/删除该问题

1 个答案:

答案 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在这里很重要的原因。