在字节数组上对小数值进行掩码,而不会在c#中浪费空间?

时间:2015-04-12 19:52:11

标签: c# bitmask bit-masks

我试图通过扩展this topic来扩展它以覆盖打包到byte []数据结构中的5位值。

我想要实现的具体目标是在80字节数组中存储总共128个5位(0-31)数值,并使用get / set函数访问和操作其中的值。阵列。

有没有人有这方面的经验?

编辑:

感谢Guffa在下面接受的答案中,这是他的类的内联版本,用于静态调用:

byte Get_5_In_BA(ref byte[] storage, int index)
{
    int bigIndex = (index * 5) / 8;
    int smallIndex = (index * 5) % 8;
    if (smallIndex > 3)
    {
        return ((byte) (((storage[bigIndex] + (storage[bigIndex + 1] * 0x0100)) >> smallIndex) & 0x1F));
    }
    return ((byte) ((storage[bigIndex] >> smallIndex) & 0x1F));
}

void Set_5_In_BA(ref byte[] storage, int index, byte value)
{
    if (value > 31) { value = 31; }
    int bigIndex = (index * 5) / 8;
    int smallIndex = (index * 5) % 8;
    int mask = 0x1F << smallIndex;
    storage[bigIndex] = (byte) ((storage[bigIndex] & ~mask) | (value << smallIndex));
    if (smallIndex > 3)
    {
        storage[bigIndex + 1] = (byte) ((storage[bigIndex + 1] & ~(mask >> 8)) | (value >> (8 - smallIndex)));
    }
}

1 个答案:

答案 0 :(得分:4)

这样的事情应该这样做:

public class FiveBit {

  private byte[] _data;

  public FiveBit(int len) {
    _data = new byte[(len * 5 + 7) / 8];
  }

  public int this[int index] {
    get {
      int i = index * 5 / 8;
      int ofs = index * 5 % 8;
      if (ofs > 3) {
        return ((_data[i] + _data[i + 1] * 256) >> ofs) & 31;
      } else {
        return (_data[i] >> ofs) & 31;
      }
    }
    set {
      int i = index * 5 / 8;
      int ofs = index * 5 % 8;
      int mask = 31 << ofs;
      _data[i] = (byte)((_data[i] & ~mask) | (value << ofs));
      if (ofs > 3) {
        _data[i + 1] = (byte)((_data[i + 1] & ~(mask >> 8)) | (value >> (8 - ofs)));
      }
    }
  }

}

注意:这不是经过严格测试,但我测试过我可以在其中放置128个随机5位值,并再次获得相同的值。您还应该对参数添加一些范围检查以使代码更加健壮,而且我没有过多考虑类名,因此您可以确定地编写更好地描述它的内容。