位屏蔽字节数组上的小数值而不浪费c#中的空间?

位屏蔽字节数组上的小数值而不浪费c#中的空间?,c#,bitmask,bit-masks,C#,Bitmask,Bit Masks,我试图通过扩展它来扩展一位,以覆盖打包到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 small

我试图通过扩展它来扩展一位,以覆盖打包到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)));
    }
}
byte Get_5_In_BA(ref byte[]存储,int索引)
{
int bigIndex=(索引*5)/8;
指数=(指数*5)%8;
如果(小索引>3)
{
返回((字节)((存储[bigIndex]+(存储[bigIndex+1]*0x0100))>>smallIndex)和0x1F));
}
返回((字节)((存储[bigIndex]>>smallIndex)&0x1F));
}
void Set_5_In_BA(参考字节[]存储,整数索引,字节值)
{
如果(值>31){value=31;}
int bigIndex=(索引*5)/8;
指数=(指数*5)%8;
int mask=0x1F>8))|(值>>(8-小索引));
}
}

像这样的东西应该可以做到:

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)));
      }
    }
  }

}
公共类五位{
专用字节[]_数据;
公共五位(整数){
_数据=新字节[(len*5+7)/8];
}
公共int这个[int索引]{
得到{
int i=指数*5/8;
int ofs=指数*5%8;
如果(ofs>3){
返回((_数据[i]+_数据[i+1]*256)>>ofs)和31;
}否则{
返回(_data[i]>>ofs)&31;
}
}
设置{
int i=指数*5/8;
int ofs=指数*5%8;
int mask=31>8)|(值>>(8-ofs));
}
}
}
}

注意:这不是粗略的测试,但我已经测试过,我可以在其中放入128个随机的5位值,然后再次取出相同的值。您还应该在参数上添加一些范围检查,以使代码更加健壮,我没有过多考虑类名,因此您肯定可以编写一些更好地描述它的内容。

我试图打包到其中的数据长度为5位,因此似乎会浪费大量空间(37.5%)除非我遗漏了什么。您不应该在
存储
参数上使用
ref
。只有当您想用方法中的另一个数组对象替换整个数组对象时,才会使用该方法。