用掩码交错比特

时间:2009-08-22 05:16:25

标签: c++ c bit-manipulation sequences bitmask

输入:

arbitrary bitset, e.g. bit positions 012345
arbitrary bit mask, e.g. (x=1) xx0x0x

输出:

xx0x1x2345

也就是说,我希望将bitset的第一位放在掩码的前0位。同样,第二个位置于掩码的第二个0中。

示例:

mask = 1001001
bits = 1101
result = 1111011

我知道这可以通过循环完成,但我想主要使用位操作。我知道你可以只使用掩码和位运算符来执行任意位置换。由于输入掩码将被多次使用,我愿意花费大量时间来设置置换掩码。

编辑:我查看了http://graphics.stanford.edu/~seander/bithacks.htmlhttp://www.hackersdelight.org/HDcode.htm的算法,但还没有找到确切的方法。

5 个答案:

答案 0 :(得分:1)

我认为012345打算成为BITSET,他使用0..5来表示0和1的混合。

但是,这似乎不是一个按位操作。我坚持一个循环..

答案 1 :(得分:1)

如果我没有弄错,你需要一个函数f(位掩码,位集),如:

  

f(0b00110101,0b000ABCDE)= 0bABC11D1E1

其中第一个参数(位掩码)相对固定。

我认为你必须遍历位掩码,并且在该循环内部你可以使用按位运算。当然你可以预先编译位掩码并保持0的位置,如{1,3,6,7,...},并通过循环遍历序列来保存一些周期。

答案 2 :(得分:0)

你确定你不需要循环吗?如果你知道比特数,你可以跳过开销,就像16或32行的位移一样,但循环会更简单。我认为没有其他方法可以做到这一点,但你现在让我考虑它

答案 3 :(得分:0)

我认为您尝试实现的效果是(使用您的示例数据,但有些不同地放置信息):

bitmask = 1001001
bitset  =  11 01
result  = 1111011

现在,如果我们将其描述为从右到左(最低有效位优先)工作,那么bitset的最后1意味着需要设置最右边的位掩码0。 bitset中的零表示位掩码的下一个0不变;下一个意味着第三个零转换为一个;最重要的1意味着第四个零被转换为1.由于bitset中没有更多的,所以这是最后的改变。请注意,这种算法的公式避免了bitset或bitmask中有多少位的问题 - 而从左到右的解释会导致很大的问题。

让我们回顾一下其他一些例子:

bitmask = 1001001      1001001      1100011000   0000000101001001
bitset  =  11 00        10 00         110  010     11100 1 00 11
result  = 1111001      1101001      1111011010   0011100111001111


bitmask = 01001101     01001011     11000010     0000000011111111
bitset  = 1 10  1      1 10 1          110 1         1101
result  = 11101111     11101111     11011011     0000110111111111

如果这种解释是正确的,那么bitset的含义会根据位掩码而变化。如果位掩码和位集限制为8位,那么对于每个位集,您可能最终计算出一组256个值,这些值可以与原始位掩码值进行“或”运算以产生结果。另一方面,您可以轻松地将结果计算为要对主数据进行OR运算的值。

答案 4 :(得分:0)

大多数交错位或通用聚合位功能都是循环的,但是以一种非显而易见的方式。

即使计数位功能也有O(log2(整数位))复杂度。

因此,如果您愿意接受O(掩码中的零数)循环,那么这可能是您最好的选择。 (无论如何,你必须有一个没有原生insert bits instruction的算法。):

unsigned blah(unsigned bitmask, unsigned bits_to_insert)
{
    unsigned insertion_bitmask= ~bitmask;

    while (insertion_bitmask)
    {
        unsigned bit_position_to_insert= insertion_bitmask & -insertion_bitmask;
        unsigned current_bit= bits_to_insert & 1;
        unsigned bit_to_insert_into_mask= (-current_bit) & bit_position_to_insert;
        bitmask|= bit_to_insert_into_mask;

        bits_to_insert>>= 1;
        insertion_bitmask&= insertion_bitmask - 1;
    }

    return bitmask;
}