开发者

Convert datatype 'long' to byte array

I have to convert values (double/float in C#) to bytes and need some help..

// Datatype long 4byte -99999999,99 to 99999999,99

// Datatype long 4byte -99999999,9 to 99999999,9

// Datatype short 2byte -999,99 to 999,99

// Datatype short 2byte -999,9 to 999,9

In my "world at home" i would just string it and ASCII.GetBytes().

But now, in this world, we have to make less possible space.

And indeed that '-99999999,99' takes 12 bytes instead of 4! if it's a 'long' datatype.

[EDIT]

Due to some help and answer I attach some results here,

long lng = -9999999999L;
byte[] test = Encoding.ASCII.GetBytes(lng.ToString());  // 11 byte
byte[] test2 = BitConverter.GetBytes(lng);              // 8 byte
byte[] mybyt = BitConverter.GetBytes(lng);              // 8 byte
byte[] bA = BitConverter.GetBytes(lng);                 // 8 byte

There still have to be one detail left to find out. The lng-variabel got 8 byte even if it helds a lower values, i.e. 99951 (I won't include the ToString() sample).

If the value are even "shorter", which m开发者_如何学编程eans -999,99 -- 999,99 it will only take 2 byte space.

[END EDIT]


Have you checked BitConverter

long lng =-9999999999L;
byte[] mybyt = BitConverter.GetBytes(lng);

hope this is what you are looking


Try to do it in this way:

long l = 4554334;

byte[] bA = BitConverter.GetBytes(l);


Be aware that in 2 bytes you can only have 4 full digits + sign, and in 4 bytes you can only have 9 digits + sign, so I had to scale your prereqs accordingly.

public static byte[] SerializeLong2Dec(double value)
{
    value *= 100;
    value = Math.Round(value, MidpointRounding.AwayFromZero);

    if (value < -999999999.0 || value > 999999999.0)
    {
        throw new ArgumentOutOfRangeException();
    }

    int value2 = (int)value;

    return BitConverter.GetBytes(value2);
}

public static double DeserializeLong2Dec(byte[] value)
{
    int value2 = BitConverter.ToInt32(value, 0);
    return (double)value2 / 100.0;
}

public static byte[] SerializeLong1Dec(double value) {
    value *= 10;
    value = Math.Round(value, MidpointRounding.AwayFromZero);

    if (value < -999999999.0 || value > 999999999.0) {
        throw new ArgumentOutOfRangeException();
    }

    int value2 = (int)value;

    return BitConverter.GetBytes(value2);
}

public static double DeserializeLong1Dec(byte[] value) {
    int value2 = BitConverter.ToInt32(value, 0);
    return (double)value2 / 10.0;
}

public static byte[] SerializeShort2Dec(double value) {
    value *= 100;
    value = Math.Round(value, MidpointRounding.AwayFromZero);

    if (value < -9999.0 || value > 9999.0) {
        throw new ArgumentOutOfRangeException();
    }

    short value2 = (short)value;

    return BitConverter.GetBytes(value2);
}

public static double DeserializeShort2Dec(byte[] value) {
    short value2 = BitConverter.ToInt16(value, 0);
    return (double)value2 / 100.0;
}

public static byte[] SerializeShort1Dec(double value) {
    value *= 10;
    value = Math.Round(value, MidpointRounding.AwayFromZero);

    if (value < -9999.0 || value > 9999.0) {
        throw new ArgumentOutOfRangeException();
    }

    short value2 = (short)value;

    return BitConverter.GetBytes(value2);
}

public static double DeserializeShort1Dec(byte[] value) {
    short value2 = BitConverter.ToInt16(value, 0);
    return (double)value2 / 10.0;
}

So that it's clear, the range of a (signed) short (16 bits) is -32,768 to 32,767 so it's quite clear that you only have 4 full digits plus a little piece (the 0-3), the range of a (signed) int (32 bits) is −2,147,483,648 to 2,147,483,647 so it's quite clear that you only have 9 full digits plus a little piece (the 0-2). Going to a (signed) long (64 bits) you have -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 so 18 digits plus a (big) piece. Using floating points you lose in accuracy. A float (32 bits) has an accuracy of around 7 digits, while a double (64 bits) has an accuracy of around 15-16 digits.


To everyone reading this question and the answers. Please note that:

//convert to bytes
long number = 123;
byte[] bytes = BitConverter.GetBytes(number);

//convert back to int64
long newNumber = BitConverter.ToInt64(bytes);

//numbers are different on x64 systems!!!
number != newNumber;

The workaround is to check which system you run on:

newNumber = BitConverter.IsLittleEndian
    ? BitConverter.ToInt64(bytes, 0)
    : BitConverter.ToInt64(bytes.Reverse().ToArray(), 0);


long longValue = 9999999999L;

        Console.WriteLine("Long value: " + longValue.ToString());

        bytes = BitConverter.GetBytes(longValue);

        Console.WriteLine("Byte array value:");

        Console.WriteLine(BitConverter.ToString(bytes));


As the other answers have pointed out, you can use BitConverter to get the byte representation of primitive types.

You said that in the current world you inhabit, there is an onus on representing these values as concisely as possible, in which case you should consider variable length encoding (though that document may be a bit abstract).

If you decide this approach is applicable to your case I would suggest looking at how the Protocol Buffers project represents scalar types as some of these types are encoded using variable length encoding which produces shorter output if the data set favours smaller absolute values. (The project is open source under a New BSD license, so you will be able to learn the technique employed from the source repository or even use the source in your own project.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜