Как получить двоичное представление IEEE 754 числа с плавающей запятой в С#

У меня есть несколько поплавков с одинарной и двойной точностью, которые я хочу записывать и читать из байта []. Есть ли что-нибудь в .Net, которое я могу использовать для преобразования их в 32- и 64-битные представления IEEE 754 и обратно?


person HasaniH    schedule 22.11.2010    source источник


Ответы (2)


.NET Single и Double уже представлены в формате IEEE-754. Вы можете использовать BitConverter.ToSingle() и ToDouble() для преобразования byte[] в число с плавающей запятой, а GetBytes() — наоборот.

person Hans Passant    schedule 22.11.2010
comment
Как мы можем сделать это без использования GetBytes(). я имею в виду использование forloops - person Satti; 10.02.2014
comment
@SriramSatti, посмотри мой ответ - person Marc Gravell; 01.07.2014

Обновление для текущего .NET/C# с ​​использованием промежутков:

static void Main()
{
    Span<byte> data = stackalloc byte[20];
    GetBytes(0, data, 0);
    GetBytes(123.45F, data, 4);
    GetBytes(123.45D, data, 8);
}

static unsafe void GetBytes(float value, Span<byte> buffer, int offset)
    => MemoryMarshal.Cast<byte, float>(buffer.Slice(offset))[0] = value;
static unsafe void GetBytes(double value, Span<byte> buffer, int offset)
    => MemoryMarshal.Cast<byte, double>(buffer.Slice(offset))[0] = value;

Если вы не хотите постоянно выделять новые массивы (что делает GetBytes), вы можете использовать код unsafe для прямой записи в буфер:

static void Main()
{
    byte[] data = new byte[20];
    GetBytes(0, data, 0);
    GetBytes(123.45F, data, 4);
    GetBytes(123.45D, data, 8);
}

static unsafe void GetBytes(float value, byte[] buffer, int offset)
{
    fixed (byte* ptr = &buffer[offset])
    {
        float* typed = (float*)ptr;
        *typed = value;
    }
}
static unsafe void GetBytes(double value, byte[] buffer, int offset)
{
    fixed (byte* ptr = &buffer[offset])
    {
        double* typed = (double*)ptr;
        *typed = value;
    }
}
person Marc Gravell    schedule 01.07.2014
comment
Каковы последствия этого способа по сравнению с созданием массива? Меня интересует, что происходит в памяти, что делает GC и т.д. - person David Klempfner; 17.11.2019
comment
@Backwards_Dave просто: один выделяет массив, а другой нет! то, что делает GC, будет полностью зависеть от того, когда этот массив недоступен, но: в какой-то момент его нужно будет собрать. Обратите внимание, что в текущем .NET/C# вы можете использовать Span<byte> API здесь и делать все это без каких-либо unsafe и без каких-либо распределений массива вообще (используя диапазон stackalloc) - см. редактирование - person Marc Gravell; 17.11.2019