我必须编写一个程序,它取3,4,5位并将它们放入24,25,26位,然后取24,25,26位(来自原始数字)并将它们放入位3,4,5的位置。我写的代码成功转移3,4,5到24,25,26,但我不明白为什么它没有相反的工作..我也想问是否有一个更容易这样做的方法..
static void Main()
{
Console.Write("Please input your number: ");
int num = Convert.ToInt32(Console.ReadLine());
int mask = 0;
int bit = 0;
int p = 0;
int numP = 0;
//take bit 3,4,5 and put them in the place of 24,25,26
for (int i = 0; i < 3; i++)
{
p = 3 + i;
numP = num >> p;
bit = numP & 1;
if (bit == 1)
{
mask = 1 << 24 + i;
num = num | mask;
}
else
{
mask = ~(1 << 24 + i);
num = num & mask;
}
}
//take bit 24,25,26 and put them in the place of 3,4,5
for (int i = 0; i < 3; i++)
{
p = 24 + i;
numP = num >> p;
bit = numP & 1;
if (bit == 1)
{
mask = 1 << 3 + i;
num = num | mask;
}
else
{
mask = ~(1 << 3 + i);
num = num & mask;
}
}
Console.WriteLine("Your new number is: {0}", num);
}
答案 0 :(得分:2)
要在复制新位之前切换需要存储原始位的位。
由于您希望将三个彼此相邻的位切换为另外三个彼此相邻的位,因此可以非常轻松地完成:
int lo = num & 0x00000038; // get bits 3-5
int hi = num & 0x07000000; // get bits 24-26
num &= ~0x07000038; // clear bits 3-5 and 24-26
num |= lo << 21; // put bits 3-5 in 24-26
num |= hi >> 21; // put bits 24-26 in 3-5
在循环中一次执行相同的一位;而不是有两个循环和复制位,你可以用一个循环来交换位,这解决了第一个循环覆盖你在第二个循环中需要的位的问题:
int numP, bit1, bit2, mask1, mask2;
//swap bits 3,4,5 with bits 24,25,26
for (int i = 0; i < 3; i++) {
// get bit 3 (,4,5)
numP = num >> (3 + i);
bit1 = numP & 1;
// get bit 24 (,25,26)
numP = num >> (24 + i);
bit2 = numP & 1;
// shift bit 3 (,4,5) to positon 24 (,25,26)
bit1 = bit1 << (24 + i);
// shift bit 24 (,25,26) to position 3 (,4,5)
bit2 = bit2 << (3 + i);
// set bit 3 (,4,5) to zero
mask1 = 1 << (3 + i);
num = num & ~mask1;
// set bit 24 (,25,26) to zero
mask2 = 1 << (24 + i);
num = num & ~mask2;
// put bit 3 (,4,5) in bit 24 (,25,26)
num = num | bit1;
// put bit 24 (,25,26) in bit 3 (,4,5)
num = num | bi2;
}
答案 1 :(得分:0)
假设您将位数从最小到最重要(正确的方式)编号:
3322 2222 2222 1111 1111 11
1098 7654 3210 9876 5432 1098 7654 3210
xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
你的面具是
0x00000038 (binary: 0000 0000 0000 0000 0000 0000 0011 1000)
将提取位3-5 0x07000000 (binary: 0000 0111 0000 0000 0000 0000 0000 0000)
将提取位24-26 代码很简单。这是一种方法:
public uint exchange_bits( uint a )
{
uint swapped = ( a & ~( 0x07000038 ) ) // clear bits 3-5 and 24-26
| ( ( a & 0x00000038 ) << 21 ) // OR in bits 3-5, shifted left 21 bits
| ( ( a & 0x07000000 ) >> 21 ) // OR in bits 24-26, shifted right 21 bits
;
return swapped ;
}
答案 2 :(得分:0)
我始终认为代码应该是人类可读的,并且只是偶然可执行的。如果您没有在紧密循环中运行它,则可以执行以下操作:
private static int SwapBits(int ind)
{
BitVector32 bv = new BitVector32(ind);
BitVector32 bcopy = bv;
bcopy[1 << 24] = bv[1 << 3];
bcopy[1 << 25] = bv[1 << 4];
bcopy[1 << 26] = bv[1 << 5];
bcopy[1 << 3] = bv[1 << 24];
bcopy[1 << 4] = bv[1 << 25];
bcopy[1 << 5] = bv[1 << 26];
return bcopy.Data;
}
产地:
old 0x02000028 00000010000000000000000000101000
new 0x05000010 00000101000000000000000000010000
如果 处于紧密循环中,我会执行以下操作:
private static int SwapBitsInt(int ind)
{
// mask out the ones we swap
int outd = ind & ~0x07000038;
// set the top 3 and bottom 3. The sections are 21 bits away.
outd |= (ind & 0x00000038) << 21;
outd |= (ind & 0x07000000) >> 21;
return outd;
}
常量0x00000038
和0x07000000
是1 << 3 | 1 << 4 | 1 << 5
和1 << 24 | 1 << 25 | 1 << 26
的结果。找到它们的一种简单方法是在Windows Calculator中使用“Programmer”模式,然后单击所需的位。