Преобразовать тип данных long в байтовый массив - PullRequest
16 голосов
/ 26 августа 2011

Мне нужно преобразовать значения (double / float в C #) в байты и мне нужна помощь.

// Тип данных long 4 байта от -99999999,99 до 99999999,99
// Тип данных long 4 байта от -99999999,9 до 99999999,9
// Тип данных короткий 2 байта от -999,99 до 999,99
// Тип данных короткий 2 байта от -999,9 до 999,9

В моем "мире дома" я бы просто записал его и ASCII.GetBytes ().

Но теперь, в этом мире, мы должны сделать меньше возможного пространства.
И действительно, '-99999999,99' занимает 12 байтов вместо 4! если это «длинный» тип данных.

[EDIT]
Из-за некоторой помощи и ответа я прилагаю некоторые результаты здесь,

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

Осталась еще одна деталь, чтобы узнать. Lng-variabel получил 8 байт, даже если он содержал более низкие значения, то есть 99951 (я не буду включать пример ToString ()).

Если значение даже «короче», что означает -999,99 - 999,99, это займет всего 2 байта.
[END EDIT]

Ответы [ 5 ]

23 голосов
/ 26 августа 2011

Вы проверили BitConverter

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

надеюсь, это то, что вы ищете

6 голосов
/ 26 августа 2011

Помните, что в 2 байтах вы можете иметь только 4 полных цифры + знак, а в 4 байтах вы можете иметь только 9 цифр + знак, поэтому мне пришлось соответствующим образом масштабировать ваши предварительные требования.

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;
}

Чтобы было ясно, диапазон (подписанного) короткого (16 битов) составляет от -32 768 до 32 767, поэтому совершенно очевидно, что у вас есть только 4 полных цифры плюс небольшой фрагмент (0-3), диапазон a (подписано) int (32 бита) - от -2 147 483 648 до 2 147 483 647, поэтому совершенно очевидно, что у вас есть только 9 полных цифр плюс небольшой фрагмент (0-2). Переходя к (подписанному) длинному (64 бита), вы получаете от -9,223,372,036,854,775,808 до 9,223,372,036,854,775,807, то есть 18 цифр плюс (большой) кусок. Используя плавающие точки, вы теряете в точности. Точность с плавающей запятой (32 бита) составляет около 7 цифр, а с двойной точностью (64 бита) - около 15-16 цифр.

6 голосов
/ 26 августа 2011

Попробуйте сделать так:

long l = 4554334;

byte[] bA = BitConverter.GetBytes(l);
1 голос
/ 26 августа 2011

Как указывалось в других ответах, вы можете использовать BitConverter, чтобы получить байтовое представление примитивных типов.

Вы сказали, что в текущем мире, в котором вы живете, есть обязанность представлять эти значения как кратко , насколько это возможно, и в этом случае вы должны рассмотреть кодирование переменной длины (хотя это документ может быть немного абстрактным).

Если вы решите, что этот подход применим в вашем случае, я бы посоветовал посмотреть, как проект Буферы протокола представляет скалярные типы , поскольку некоторые из этих типов кодируются с использованием кодирования переменной длины, который производит более короткий вывод, если набор данных предпочитает меньшие абсолютные значения. (Проект имеет открытый исходный код по Новой лицензии BSD , поэтому вы сможете изучить технику, используемую в репозитории исходных кодов , или даже использовать источник в своем собственном проекте.)

1 голос
/ 26 августа 2011
long longValue = 9999999999L;

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

        bytes = BitConverter.GetBytes(longValue);

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

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