C#中0-31小数字数组(5位/数)的高效编解码方案咨询
在C#中高效存储0-31数字的编解码方案
选择byte数组还是BitArray?
优先用byte数组,原因很直接:
- BitArray底层依赖int数组实现,每个元素占32位,额外的对象头、数组管理开销比直接用byte数组大;
- 直接操作byte的位运算无需经过BitArray的方法调用层,速度更快,内存占用也更紧凑(比如8个数字仅需5字节,BitArray存40位至少要2个int,占8字节)。
编码实现(List → byte数组)
输入为每个元素0-31的List
public static byte[] Encode(List<byte> input) { int totalBytes = (input.Count * 5 + 7) / 8; // 计算所需总字节数 byte[] result = new byte[totalBytes]; int bitPosition = 0; foreach (byte num in input) { // 可选:输入合法性校验,按需保留 if (num > 31) throw new ArgumentOutOfRangeException(nameof(num), "数字必须在0-31范围内"); int byteIndex = bitPosition / 8; int bitOffset = bitPosition % 8; // 将数字的位写入当前字节 result[byteIndex] |= (byte)(num << bitOffset); // 处理跨字节溢出:当剩余位不足5位时,把溢出部分写入下一个字节 if (bitOffset > 3) { result[byteIndex + 1] |= (byte)(num >> (8 - bitOffset)); } bitPosition += 5; } return result; }
解码实现(byte数组 → List)
将编码后的byte数组还原为每个元素0-31的List
public static List<byte> Decode(byte[] input) { int totalNumbers = (input.Length * 8) / 5; List<byte> result = new List<byte>(totalNumbers); int bitPosition = 0; for (int i = 0; i < totalNumbers; i++) { int byteIndex = bitPosition / 8; int bitOffset = bitPosition % 8; byte num; if (bitOffset <= 3) { // 提取当前字节的对应位,若跨字节则补充下一字节的溢出位 num = (byte)((input[byteIndex] >> bitOffset) & 0x1F); if (bitOffset + 5 > 8) { num |= (byte)(input[byteIndex + 1] << (8 - bitOffset)); } } else { // 剩余位不足5位,从当前字节和下一字节拼接后取低5位 num = (byte)((input[byteIndex] >> bitOffset) | (input[byteIndex + 1] << (8 - bitOffset))); num &= 0x1F; } result.Add(num); bitPosition += 5; } return result; }
优化说明
- 全程用原生位运算,避免多余临时对象,最小化性能开销;
- 预先计算集合长度,避免List动态扩容的额外消耗;
- 输入合法性校验可根据实际场景移除,进一步提升编码速度。
内容的提问来源于stack exchange,提问作者Jiri Hudecek
相关产品推荐
相关产品推荐

