Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting 3 bytes into signed integer in C#

I'm trying to convert 3 bytes to signed integer (Big-endian) in C#.

I've tried to use BitConverter.ToInt32 method, but my problem is what value should have the lats byte.

Can anybody suggest me how can I do it in different way?

I also need to convert 5 (or 6 or 7) bytes to signed long, is there any general rule how to do it?

Thanks in advance for any help.

like image 325
Rafal Spacjer Avatar asked Nov 12 '11 12:11

Rafal Spacjer


3 Answers

As a last resort you could always shift+add yourself:

byte b1, b2, b3;

int r = b1 << 16 | b2 << 8 | b3;

Just swap b1/b2/b3 until you have the desired result.

On second thought, this will never produce negative values.
What result do you want when the msb >= 0x80 ?


Part 2, brute force sign extension:

    private static int Bytes2Int(byte b1, byte b2, byte b3)
    {
        int r = 0;
        byte b0 = 0xff;

        if ((b1 & 0x80) != 0) r |= b0 << 24;
        r |= b1 << 16;
        r |= b2 << 8;
        r |= b3;
        return r;
    }

I've tested this with:

      byte[] bytes = BitConverter.GetBytes(p);
      int r = Bytes2Int(bytes[2], bytes[1], bytes[0]);
      Console.WriteLine("{0} == {1}", p, r);

for several p.

like image 172
Henk Holterman Avatar answered Sep 27 '22 22:09

Henk Holterman


The last value should be 0 if it isn't set for a positive number, 256 for a negative.

To know what you should pass in, you can try converting it the other way:

var bytes = BitConverter.GetBytes(i);
int x = BitConverter.ToInt32(bytes, 0);
like image 37
Oskar Kjellin Avatar answered Sep 28 '22 00:09

Oskar Kjellin


To add to the existing answers here, there's a bit of a gotcha in that Bitconverter.ToInt32() will throw an ArgumentException if the array is less than sizseof(int) (4) bytes in size;

Destination array is not long enough to copy all the items in the collection. Check array index and length.

Given an array less than sizeof(int) (4) bytes in size, you can compensate for left/right padding like so;

Right-pad

Results in positive Int32 numbers

int intByteSize = sizeof(int);
byte[] padded = new byte[intByteSize];
Array.Copy(sourceBytes, 0, padded, 0, sourceBytes.Length);
sourceBytes = padded;

Left-pad

Results in negative Int32 numbers, assuming non-zero value at byte index sourceBytes.Length - 1.

int intByteSize = sizeof(int);
byte[] padded = new byte[intByteSize];
Array.Copy(sourceBytes, 0, padded, intByteSize - sourceBytes.Length, sourceBytes.Length);
sourceBytes = padded;

Once padded, you can safely call int myValue = BitConverter.ToInt32(sourceBytes, 0);.

like image 43
DiskJunky Avatar answered Sep 27 '22 22:09

DiskJunky