【问题标题】:Bit-shifting a byte array by N bits将字节数组位移 N 位
【发布时间】:2010-11-19 12:30:25
【问题描述】:

您好,关于位移的快速问题

我有一个十六进制值:new byte[] { 0x56, 0xAF }; 这是0101 0110 1010 1111

我要前N位,比如12。

然后我必须右移最低 4 位 (16 - 12) 以获得0000 0101 0110 1010 (1386 dec)。

我无法绕开它并使其可扩展为 n 位。

【问题讨论】:

    标签: c# bit-manipulation bit-shift


    【解决方案1】:

    前段时间我编写了这两个函数,第一个将 byte[] 向左移动指定数量的位,第二个向右移动:

    左移:

    public byte[] ShiftLeft(byte[] value, int bitcount)
    {
        byte[] temp = new byte[value.Length];
        if (bitcount >= 8)
        {
            Array.Copy(value, bitcount / 8, temp, 0, temp.Length - (bitcount / 8));
        }
        else
        {
            Array.Copy(value, temp, temp.Length);
        }
        if (bitcount % 8 != 0)
        {
            for (int i = 0; i < temp.Length; i++)
            {
                temp[i] <<= bitcount % 8;
                if (i < temp.Length - 1)
                {
                    temp[i] |= (byte)(temp[i + 1] >> 8 - bitcount % 8);
                }
            }
        }
        return temp;
    }
    

    右移:

    public byte[] ShiftRight(byte[] value, int bitcount)
    {
        byte[] temp = new byte[value.Length];
        if (bitcount >= 8)
        {
            Array.Copy(value, 0, temp, bitcount / 8, temp.Length - (bitcount / 8));
        }
        else
        {
            Array.Copy(value, temp, temp.Length);
        }
        if (bitcount % 8 != 0)
        {
            for (int i = temp.Length - 1; i >= 0; i--)
            {
                temp[i] >>= bitcount % 8;
                if (i > 0)
                {
                    temp[i] |= (byte)(temp[i - 1] << 8 - bitcount % 8);
                }
            }
        }
        return temp;
    }
    

    如果您需要进一步解释,请对此发表评论,然后我将编辑我的帖子以进行澄清...

    【讨论】:

    • 提前复制 8bit 移位溢出是个不错的主意。在我看到这个想法之前,我的实现有 2 个嵌套的 for-s 来处理溢出。
    【解决方案2】:

    您可以使用 BitArray,然后轻松地将每个位复制到右侧,从右侧开始。

    http://msdn.microsoft.com/en-us/library/system.collections.bitarray_methods.aspx

    【讨论】:

      【解决方案3】:

      你想要...

      var HEX = new byte[] {0x56, 0xAF};
      var bits = new BitArray(HEX);
      int bitstoShiftRight = 4;
      for (int i = 0; i < bits.Length; i++)
      {
         bits[i] = i < (bits.Length - bitstoShiftRight) ? bits[i + bitstoShiftRight] : false;
      }
      bits.CopyTo(HEX, 0);
      

      【讨论】:

      • 谢谢,我喜欢这种方法,问题是 BitArray 构造函数更改了每个字节的 Endian 顺序,一旦方法完成,该值就会出错,id 需要在之前反转每个字节的位顺序用 byes 实例化位数组
      【解决方案4】:

      如果您总共有 k 位,并且您想要“第一个”(如最高有效位)n 位,您可以简单地右移 k-n 次。最后的 k-n 位将被删除,通过某种“下降”结束,第一个 n 将被移动到最低有效的一侧。

      【讨论】:

      • 感谢您的回复,问题是我无法真正移位字节数组,我需要单独执行它们然后我丢失了溢出,所以我的替代方法是将整个 16 位转换为一个 int 16 并在那时移位,不是我想要的,因为我现在需要知道长度并转换为该类型然后移位
      【解决方案5】:

      使用类 C 表示法回答,假设 bits_in_byte 是在别处确定的字节中的位数:

      int remove_bits_count= HEX.count*bits_in_byte - bits_to_keep;
      int remove_bits_in_byte_count= remove_bits_count % bits_in_byte;
      
      if (remove_bits_count > 0)
      {
          for (int iteration= 0; iteration<min(HEX.count, (bits_to_keep + bits_in_byte - 1)/bits_in_byte); ++iteration)
          {
              int write_index= HEX.count - iteration - 1;
              int read_index_lo= write_index - remove_bits_count/bits_in_byte;
      
              if (read_index_lo>=0)
              {
                  int read_index_hi= read_index_lo - (remove_bits_count + bits_in_byte - 1)/bits_in_byte;
      
                  HEX[write_index]= 
                      (HEX[read_index_lo] >> remove_bits_in_byte_count) | 
                      (HEX[read_index_hi] << (bits_in_byte - remove_bits_in_byte_count));
              }
              else
              {
                  HEX[write_index]= 0;
              }
          }
      }
      

      假设您要覆盖原始数组,您基本上会获取您写入的每个字节并计算出它将从中获得移位位的字节。您从数组的末尾走到前面,以确保您永远不会覆盖您需要读取的数据。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-06
        • 1970-01-01
        • 1970-01-01
        • 2021-11-30
        • 2012-08-21
        相关资源
        最近更新 更多