Битсет для плавающего числа или двойное значение с ++ - PullRequest
0 голосов
/ 03 октября 2018

У меня есть два набора битов двоичного представления IEEE754 с плавающей запятой (32 бита) и двойного (64 бита).Как я могу преобразовать этот набор битов в РЕАЛЬНОЕ число с плавающей запятой или двойное число?

Ответы [ 3 ]

0 голосов
/ 03 октября 2018

Во-первых, каждый не просто представляет IEEE 754 с плавающей точкой .Есть много, что входит в такое представление.Допустим, вы получили переменную bitset: param и хотите преобразовать ее в float.Чтобы гарантировать, что это действительное преобразование, вам необходимо убедиться, что:

  • param.size() == sizeof(float) * CHAR_BIT
  • Порядковый номер , из которого param было закодировано, соответствует endian::native
  • numeric_limits<float>::is_iec559 истинно
  • Радиус, с которого было закодировано param, соответствует numeric_limits<float>::radix

Если все они истинны, то эти биты фактическив формате вашего внутреннего представления с плавающей запятой, и вы можете конвертировать с помощью простой функции, подобной этой (при условии, что sizeof(unsigned long) == sizeof(float) и sizeof(unsigned long long) == sizeof(double)):

double foo(const bitset<sizeof(double) * CHAR_BIT>& param) {
    const auto val = param.to_ullong();
    double result;

    memcpy(&result, &val, sizeof(double));

    return result;
}

float foo(const bitset<sizeof(float) * CHAR_BIT>& param) {
    const auto val = param.to_ulong();
    float result;

    memcpy(&result, &val, sizeof(float));

    return result;
}
0 голосов
/ 03 октября 2018

Вот решение, которое не опирается на реализацию C ++ с использованием типов IEEE-754.

Пусть s будет первым битом набора битов.

Пусть e будетследующие 8 или 11 бит для 32-битной или 64-битной версии соответственно.

Пусть f будут оставшимися 23 или 52 битами соответственно.

Пусть Ebias будет 127 или1023 соответственно.

Пусть Emax будет 255 или 2047 соответственно.

Пусть Fscale будет 0x1p-23 или 0x1p-52 соответственно.

Тогда этоcode возвращает значение набора битов, интерпретируемого как базовый двоичный объект IEEE-754 с плавающей запятой:

// Interpret the sign.
double S = s ? -1 : +1;

// Classify the exponent.
if (e == 0)
    // The value is zero or subnormal.
    return S * std::ldexp(f*Fscale, 1-Ebias);

else if (e < eMax)
    // The value is normal.
    return S * std::ldexp(1 + f*Fscale, e-Ebias);

else
    // The value is NaN or infinite.
    if (f == 0)
        // The value is infinite.
        return S * INFINITY;
    else
        // The value is a NaN.
        return NAN;

Это не устанавливает все биты в NAN (включая бит знака) для соответствия точным битамв битах.Нет портативного способа сделать это;обычно это делается путем копирования битов в объект float или double с использованием memcpy или другого копирования с использованием символьного типа, и для этого требуется, чтобы реализация C ++ использовала тип float или doubleэто IEEE-754.И, конечно же, вышесказанное требует, чтобы реализация C ++ поддерживала NAN и INFINITY, и чтобы тип с плавающей точкой в ​​реализации C ++ был способен представлять значение.

0 голосов
/ 03 октября 2018

Используйте bitset::to_ullong() и memcpy() биты.

...