比特交换麻烦C#

时间:2014-05-16 22:36:07

标签: c# bits operations

我必须编写一个程序,它取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);

}

3 个答案:

答案 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;
}

常量0x000000380x070000001 << 3 | 1 << 4 | 1 << 51 << 24 | 1 << 25 | 1 << 26的结果。找到它们的一种简单方法是在Windows Calculator中使用“Programmer”模式,然后单击所需的位。