c# - 从位的一部分获取整数的最快方法

jaa*_*anq 2 c# arrays performance bit

我有 byte[] byteArray,通常是 byteArray.Length = 1-3

我需要将数组分解为位,取一些位(例如,5-17),然后将这些位转换为 Int32。

我试图这样做

private static IEnumerable<bool> GetBitsStartingFromLSB(byte b)
{
    for (int i = 0; i < 8; i++)
    {
        yield return (b % 2 != 0);
        b = (byte)(b >> 1);
    }
}
public static Int32 Bits2Int(ref byte[] source, int offset, int length)
{
    List<bool> bools = source.SelectMany(GetBitsStartingFromLSB).ToList();
    bools = bools.GetRange(offset, length);
    bools.AddRange(Enumerable.Repeat(false, 32-length).ToList() );
    int[] array = new int[1];
    (new BitArray(bools.ToArray())).CopyTo(array, 0);
    return array[0];           
}
Run Code Online (Sandbox Code Playgroud)

但是这个方法太慢了,不得不经常调用。

我怎样才能更有效地做到这一点?

非常感谢!现在我这样做:

public static byte[] GetPartOfByteArray(  byte[] source, int offset, int length)
    {
        byte[] retBytes = new byte[length];
        Buffer.BlockCopy(source, offset, retBytes, 0, length);
        return retBytes;
    }
    public static Int32 Bits2Int(byte[] source, int offset, int length)
    {
        if (source.Length > 4)
        {
            source = GetPartOfByteArray(source, offset / 8, (source.Length - offset / 8 > 3 ? 4 : source.Length - offset / 8));
            offset -= 8 * (offset / 8);
        }
        byte[] intBytes = new byte[4];
        source.CopyTo(intBytes, 0);
        Int32 full = BitConverter.ToInt32(intBytes);
        Int32 mask = (1 << length) - 1;
        return (full >> offset) & mask;
    }
Run Code Online (Sandbox Code Playgroud)

它的工作速度非常快!

Mar*_*ell 7

如果您追求“快速”,那么最终您需要使用位逻辑来完成此操作,而不是 LINQ 等。我不会编写实际代码,但您需要:

  • 使用您的偏移量/ 8 % 8来查找起始字节和该字节内的位偏移量
  • 组合您需要的任意多个字节 - 如果您使用的是 32 位数字(因为可能存在偏移),则很可能最多为 5 个字节;例如进入 a long,以您期望的任何字节序(大概是大字节序?)
  • >>在组合值上使用右移 ( ) 来删除您需要应用位偏移的许多位 (即value >>= offset % 8;)
  • 屏蔽掉您不想要的任何位;例如value &= ~(-1L << length);-1给你全 1;在右手边<< length创建length零,并将~全零交换为 1,将 1 交换为零,所以你现在length在右手边有一个)
  • 如果该值是有符号的,则需要考虑如何处理负数,特别是如果您并不总是读取 32 位