如何读取具有偏移和c#中尺寸的字节[]的int

发布于 2025-01-28 05:06:45 字数 2313 浏览 1 评论 0原文

我需要一个将作为参数作为偏移量和大小的函数来读取字节数组中的int值。

int GetInt(byte[] data, int bitOffset, int bitSize)

例如,我有以下字节数组:

66 DC 00 00 6A DC 00 00
66 DC 00 00 58 DC 00 00
54 DC 00 00 50 DC 00 00
4C DC 00 00 00 00 00 00
00 00 00 00 00 00 00 08
F0 FF FF 9F F4 7F 20 9A
91 EB 85 88 3F 6E 00 80
3D 6E 00 80 3B 6E 00 00

位相同:

01100110  00111011  00000000  00000000  01010110  00111011  00000000  00000000
01100110  00111011  00000000  00000000  00011010  00111011  00000000  00000000
00101010  00111011  00000000  00000000  00001010  00111011  00000000  00000000
00110010  00111011  00000000  00000000  00000000  00000000  00000000  00000000
00000000  00000000  00000000  00000000  00000000  00000000  00000000  00010000
00001111  11111111  11111111  11111001  00101111  11111110  00000100  01011001
10001001  11010111  10100001  00010001  11111100  01110110  00000000  00000001
10111100  01110110  00000000  00000001  11011100  01110110  00000000  00000000

我如何最有效地确保以下函数具有这些返回值?:

var a = GetInt(data, 0, 32); // a = 56422
var b = GetInt(data, 313, 11); // b = 4

“

编辑:在此处bytes作为C#array:

new byte[] { 0x66, 0xDC, 0x00, 0x00, 0x6A, 0xDC, 0x00, 0x00, 0x66, 0xDC, 0x00, 0x00, 0x58, 0xDC, 0x00, 0x00, 0x54, 0xDC, 0x00, 0x00, 0x50, 0xDC, 0x00, 0x00, 0x4C, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xF0, 0xFF, 0xFF, 0x9F, 0xF4, 0x7F, 0x20, 0x9A, 0x91, 0xEB, 0x85, 0x88, 0x3F, 0x6E, 0x00, 0x80, 0x3D, 0x6E, 0x00, 0x80, 0x3B, 0x6E, 0x00, 0x00 }

Edit :edit:edit:edit:edit:edit:edit:edit 2: 我也已经实施了自己的解决方案,可以在此处使用本文的所有价值观。我只是对我的解决方案非常不满意,因为我不想每次都将数组传递到一个bitarray。要读取文件,此功能称为数十万次。

public static int GetdInt(this byte[] data, int bitOffset, int bitSize)
{
    var bits = new BitArray(data);

    var output = 0;

    for(var bitIndex = 0; bitIndex < bitSize; bitIndex++)
    {
        var bit = bits.Get(bitOffset + bitIndex) ? 1 : 0;
        output |= bit << bitIndex;
    }

    return output;
}

I need a function that takes as parameters an offset and a size of bits to read an int value from a byte array.

int GetInt(byte[] data, int bitOffset, int bitSize)

For example, I have the following array of bytes:

66 DC 00 00 6A DC 00 00
66 DC 00 00 58 DC 00 00
54 DC 00 00 50 DC 00 00
4C DC 00 00 00 00 00 00
00 00 00 00 00 00 00 08
F0 FF FF 9F F4 7F 20 9A
91 EB 85 88 3F 6E 00 80
3D 6E 00 80 3B 6E 00 00

Same in bits:

01100110  00111011  00000000  00000000  01010110  00111011  00000000  00000000
01100110  00111011  00000000  00000000  00011010  00111011  00000000  00000000
00101010  00111011  00000000  00000000  00001010  00111011  00000000  00000000
00110010  00111011  00000000  00000000  00000000  00000000  00000000  00000000
00000000  00000000  00000000  00000000  00000000  00000000  00000000  00010000
00001111  11111111  11111111  11111001  00101111  11111110  00000100  01011001
10001001  11010111  10100001  00010001  11111100  01110110  00000000  00000001
10111100  01110110  00000000  00000001  11011100  01110110  00000000  00000000

How do I most efficiently ensure that the following function has these return values?:

var a = GetInt(data, 0, 32); // a = 56422
var b = GetInt(data, 313, 11); // b = 4

enter image description here

EDIT: Here the bytes as an C# Array:

new byte[] { 0x66, 0xDC, 0x00, 0x00, 0x6A, 0xDC, 0x00, 0x00, 0x66, 0xDC, 0x00, 0x00, 0x58, 0xDC, 0x00, 0x00, 0x54, 0xDC, 0x00, 0x00, 0x50, 0xDC, 0x00, 0x00, 0x4C, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xF0, 0xFF, 0xFF, 0x9F, 0xF4, 0x7F, 0x20, 0x9A, 0x91, 0xEB, 0x85, 0x88, 0x3F, 0x6E, 0x00, 0x80, 0x3D, 0x6E, 0x00, 0x80, 0x3B, 0x6E, 0x00, 0x00 }

EDIT 2:
I have already implemented my own solution as well, with which i could take all the values for this post here. Im just very unhappy with my solution because i dont want to pass the array into a BitArray every time. To read a file, this function is called several hundred thousand times.

public static int GetdInt(this byte[] data, int bitOffset, int bitSize)
{
    var bits = new BitArray(data);

    var output = 0;

    for(var bitIndex = 0; bitIndex < bitSize; bitIndex++)
    {
        var bit = bits.Get(bitOffset + bitIndex) ? 1 : 0;
        output |= bit << bitIndex;
    }

    return output;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小耗子 2025-02-04 05:06:45

C#90字节

    int GetInt(byte[] d,int o,int b)=>Enumerable.Range(o,b).Sum(i=>(d[i/8]>>i%8)%2>0?1<<i-o:0);

我已经用代码打高尔夫的形式写了这篇文章,以嘲笑您的问题像代码高尔夫一样读取,并且您没有显示自己的任何尝试;)

这是对未来任何答案者的单位测试。 (OP这也可能对您有所帮助):

[TestMethod]
public void Test()
{
    var bytes = new byte[]
    {
        0x66, 0xDC, 0x00, 0x00, 0x6A, 0xDC, 0x00, 0x00,
        0x66, 0xDC, 0x00, 0x00, 0x58, 0xDC, 0x00, 0x00,
        0x54, 0xDC, 0x00, 0x00, 0x50, 0xDC, 0x00, 0x00,
        0x4C, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
        0xF0, 0xFF, 0xFF, 0x9F, 0xF4, 0x7F, 0x20, 0x9A,
        0x91, 0xEB, 0x85, 0x88, 0x3F, 0x6E, 0x00, 0x80,
        0x3D, 0x6E, 0x00, 0x80, 0x3B, 0x6E, 0x00, 0x00
    };
    RunTest(0, 32, 56422);
    RunTest(313, 11, 4);

    void RunTest(int offset, int bitSize, int expected)
    {
        var actual = GetInt(bytes, offset, bitSize);
        Assert.AreEqual(actual, expected);
    }
}

编辑:由于您在这里显示自己的尝试是一个非代码高尔夫的答案:

//first write a function that gets a bit value from the byte[]
bool GetBitFromByteArray(byte[] data, int bitNumber)
{
    //8 bits per byte.
    const int sizeOfByte = 8;
    
    var byteNumber = bitNumber / sizeOfByte;//index within the byte array. Integer division always rounds down
    var bitNumberWithinTheByte = bitNumber % sizeOfByte;//bit index within that byte

    //now write a function that gets a bit value from a byte
    return GetBitFromByte(data[byteNumber], bitNumberWithinTheByte);
}

bool GetBitFromByte(byte byteValue, int bitNumber)
{
    //bit shift so that the bit in question is in the least significant place
    var shifted = byteValue >> bitNumber;

    //mod 2 checks if the least significant bit is 0 or 1
    return shifted % 2 > 0;
}

int GetInt(byte[] data, int offset, int bitCount)
{
    //get bit values in order
    var bitValues = new List<bool>(bitCount);
    for (int i = 0; i < bitCount; i++)
    {
        bitValues.Add(GetBitFromByteArray(data, i + offset));
    }

    //sum up the bit values as powers of 2
    var intValue = 0;
    for (int i = 0; i < bitCount; i++)
    {
        var bitValue = bitValues[i];
        if (bitValue) intValue += 1 << i;//1<<i is equivalent to 2^i
    }

    return intValue;
}

如果您担心性能和数组分配,那么代码高尔夫的答案实际上会更好。

C# 90 bytes

    int GetInt(byte[] d,int o,int b)=>Enumerable.Range(o,b).Sum(i=>(d[i/8]>>i%8)%2>0?1<<i-o:0);

I've written this in code golfed form to poke fun at the fact that your question reads like code golf, and that you haven't shown any attempt of your own ;)

Here is a unit test for any future answerers. (OP this might be helpful to you, too):

[TestMethod]
public void Test()
{
    var bytes = new byte[]
    {
        0x66, 0xDC, 0x00, 0x00, 0x6A, 0xDC, 0x00, 0x00,
        0x66, 0xDC, 0x00, 0x00, 0x58, 0xDC, 0x00, 0x00,
        0x54, 0xDC, 0x00, 0x00, 0x50, 0xDC, 0x00, 0x00,
        0x4C, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
        0xF0, 0xFF, 0xFF, 0x9F, 0xF4, 0x7F, 0x20, 0x9A,
        0x91, 0xEB, 0x85, 0x88, 0x3F, 0x6E, 0x00, 0x80,
        0x3D, 0x6E, 0x00, 0x80, 0x3B, 0x6E, 0x00, 0x00
    };
    RunTest(0, 32, 56422);
    RunTest(313, 11, 4);

    void RunTest(int offset, int bitSize, int expected)
    {
        var actual = GetInt(bytes, offset, bitSize);
        Assert.AreEqual(actual, expected);
    }
}

Edit: Since you showed your own attempt here is a non code-golfed answer:

//first write a function that gets a bit value from the byte[]
bool GetBitFromByteArray(byte[] data, int bitNumber)
{
    //8 bits per byte.
    const int sizeOfByte = 8;
    
    var byteNumber = bitNumber / sizeOfByte;//index within the byte array. Integer division always rounds down
    var bitNumberWithinTheByte = bitNumber % sizeOfByte;//bit index within that byte

    //now write a function that gets a bit value from a byte
    return GetBitFromByte(data[byteNumber], bitNumberWithinTheByte);
}

bool GetBitFromByte(byte byteValue, int bitNumber)
{
    //bit shift so that the bit in question is in the least significant place
    var shifted = byteValue >> bitNumber;

    //mod 2 checks if the least significant bit is 0 or 1
    return shifted % 2 > 0;
}

int GetInt(byte[] data, int offset, int bitCount)
{
    //get bit values in order
    var bitValues = new List<bool>(bitCount);
    for (int i = 0; i < bitCount; i++)
    {
        bitValues.Add(GetBitFromByteArray(data, i + offset));
    }

    //sum up the bit values as powers of 2
    var intValue = 0;
    for (int i = 0; i < bitCount; i++)
    {
        var bitValue = bitValues[i];
        if (bitValue) intValue += 1 << i;//1<<i is equivalent to 2^i
    }

    return intValue;
}

If you are worried about performance and array allocation, the code golfed answer will actually be better.

万劫不复 2025-02-04 05:06:45

使用 bitarray bitConverter

int GetInt(byte[] data, int bitOffset, int bitSize)
{
    var bits = new BitArray(data).RightShift(bitOffset);
    bits.Length = bitSize;
    var bytes = new byte[4];
    bits.CopyTo(bytes, 0);
    return BitConverter.ToInt32(bytes);
}

Solution using BitArray and BitConverter

int GetInt(byte[] data, int bitOffset, int bitSize)
{
    var bits = new BitArray(data).RightShift(bitOffset);
    bits.Length = bitSize;
    var bytes = new byte[4];
    bits.CopyTo(bytes, 0);
    return BitConverter.ToInt32(bytes);
}
木格 2025-02-04 05:06:45

这是一种可能的策略,逐步阅读字节,直到读取足够的位,然后丢弃任何多余的位置。通过了两个测试用例,但这还不是足够的测试IMO,还要做更多的事情。

static int GetInt(byte[] data, int bitOffset, int bitSize)
{
    // first chunk is special, lower bits are discarded immediately
    // to prevent trying to put more than 32 bits in `result`
    // when `bitSize == 32` and `bitOffset != 0`
    int byteOffset = bitOffset >> 3;
    int result = data[byteOffset] >> (bitOffset & 7);
    int resultOffset = 8 - (bitOffset & 7);
    // the "rest", whole bytes are read from data and put into their place in the result
    while (resultOffset < bitSize)
    {
        byteOffset++;
        result |= data[byteOffset] << resultOffset;
        resultOffset += 8;
    }
    // in general too many bits have been read at this point, discard excess
    return result & (int)(uint.MaxValue >> -bitSize);
}

还有其他可能的策略。例如,使用bitConverter class(或其他技巧)读取整个int零件范围。这有可能提高效率,但是有一些不幸的细节需要解决何时目标范围没有越过阵列的末端,而是包含它们的字节平方的整数。

bitsize = 0时,我认为多余的位在末尾被丢弃的方式无法正常工作,我认为这对支持很有趣,但是可以通过将其作为特殊情况来轻松完成。与不同(1&lt;&lt; bitsize)-1,我使用的方式确实适用于32位。

Here is one possible strategy, reading the bytes one-by-one until enough bits have been read, and then discarding any excess. Passed the two test cases, but that's not sufficient testing IMO, do some more.

static int GetInt(byte[] data, int bitOffset, int bitSize)
{
    // first chunk is special, lower bits are discarded immediately
    // to prevent trying to put more than 32 bits in `result`
    // when `bitSize == 32` and `bitOffset != 0`
    int byteOffset = bitOffset >> 3;
    int result = data[byteOffset] >> (bitOffset & 7);
    int resultOffset = 8 - (bitOffset & 7);
    // the "rest", whole bytes are read from data and put into their place in the result
    while (resultOffset < bitSize)
    {
        byteOffset++;
        result |= data[byteOffset] << resultOffset;
        resultOffset += 8;
    }
    // in general too many bits have been read at this point, discard excess
    return result & (int)(uint.MaxValue >> -bitSize);
}

There are other possible strategies. For example, reading a whole int or long with the BitConverter class (or other tricks) and then doing some shifting and masking to extract the target range of bits from that. That has the potential to be more efficient, but has some unfortunate details to take care of when the target range doesn't cross the end of the array but the byte-aligned integer that contains them would.

The way the excess bits are discarded at the end doesn't work properly when bitSize = 0, which I did not think is interesting to support, but could be done easily by handling that as a special case. Unlike (1 << bitSize) - 1, the way I used does work for 32 bits.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文