如何交错两个二进制数的一部分?

How can I interleave a section of two binary numbers?

我正在尝试将两个二进制整数“合并”为一个,但我似乎做错了。

我想做的操作是:

Number of bits to merge = 3 (precomputed parameter)

Int 1 : 10010
Int 2 : 11011

给定这两个数字,将每个数字的 3 位附加到结果(从左到右):

Result : 11 01 00. 

表示第一个整数的第一位 和第二个整数的第一位。然后是第二位 第一个整数和第二个整数的第二位......等等 “要合并的位数”次。

另一个带有字母的例子是:

Number of bits to merge = 4

Int1: abcde
Int2: xyzwt

Result: ax by cz dw

我的想法是使用一个 for 循环,其中包含我必须设置的位数并附加到结果编号,但我不知道如何“附加”。

创建位掩码,用于select保留哪些位和多少位:

int mask = (1 << 3) - 1;    // results in 0000 0000 0000 0111

接下来你必须考虑你想要从每个输入整数中获得哪些位位置,我将它们称为 i1 和 i2:

// i1 = 0000 0000 0001 0010
// i2 = 0000 0000 0001 1011
int mask_shifted = mask << 3; // results in 0000 0000 0011 1000

现在您可以将掩码应用于整数并将结果与​​位运算合并:

int applied_i1 = i1 & mask_i1; // results in 0000 0000 0001 0000
int applied_i2 = i2 & mask_i2; // results in 0000 0000 0001 1000
int result = (applied_i2 << 1) | (applied_i1 >> 3); // results in 0000 0000 0011 0100

您可以循环设置每个位:

std::uint32_t merge(std::size_t start, std::size_t numberOfBits, int i1, int i2) {
    if (start == 0 || start > sizeof(int) * 8) return 0;
    if (numberOfBits == 0 || numberOfBits > 16) return 0;
    if (start < numberOfBits) return 0;
    
    int result = 0;
    for (std::size_t i = 0; i < numberOfBits; ++i) {
        std::size_t srcPos = start - 1 - i;
        std::size_t destPos = 2 * (numberOfBits - i) - 1;
        result |= (i1 & (1 << srcPos)) >> srcPos << destPos;
        result |= (i2 & (1 << srcPos)) >> srcPos << (destPos - 1);
    }
    return result;
}

int main() {
    std::size_t start = 5;
    std::size_t numberOfBits = 3;
    int i1 = 0b10010;
    int i2 = 0b11011;
    return merge(start, numberOfBits, i1, i2);
}

i1 & (1 << (start - 1 - i)) 从左边读取 i-th 位。 >> (start - 1 - i) 将其向右移动。 << (2 * (numberOfBits - i) - 1) 分别。 << (2 * (numberOfBits - i) - 2) 将其移动到结果中的正确位置。

测试输入:

Start : 5
Number of bits : 3
Int 1 : 0b10010
Int 2 : 0b11011

输出:

52 // == 0b110100

并输入:

Start : 4
Number of bits : 2
Int 1 : 0b1010
Int 2 : 0b0101

输出:

9 // == 0b1001