如何交错两个二进制数的一部分?
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
我正在尝试将两个二进制整数“合并”为一个,但我似乎做错了。
我想做的操作是:
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