4

I have two IEEE754 binary representation bitsets of float(32bit) and double (64bit). How I can convert this bitsets to REAL float or double number?

Nikolay
  • 41
  • 5

3 Answers3

5

Use bitset::to_ullong() and memcpy() the bits.

Swordfish
  • 12,971
  • 3
  • 21
  • 43
  • Note though that will only work on systems using that format for floats which is *not guaranteed* (maybe endianness, maybe just different formats entirely). If you need to support other systems, an actual conversion will be needed. – Fire Lancer Oct 03 '18 at 12:08
  • @FireLancer I don't think you're correct. The intermediate `ulong` will simply store whatever the bitset had, and we already know it's in IEEE754. – Bartek Banachewicz Oct 03 '18 at 12:10
  • 1
    @BartekBanachewicz And if the system the code is running on is *not* IEEE754, then the result `float` or `double` you `memcpy` into will not have the expected value. – Fire Lancer Oct 03 '18 at 12:10
  • Right, that's true. – Bartek Banachewicz Oct 03 '18 at 12:13
1

Here is a solution that does not rely on the C++ implementation using IEEE-754 types.

Let s be the first bit of the bitset.

Let e be the next 8 or 11 bits for 32-bit or 64-bit, respectively.

Let f be the remaining 23 or 52 bits, respectively.

Let Ebias be 127 or 1023, respectively.

Let Emax be 255 or 2047, respectively.

Let Fscale be 0x1p-23 or 0x1p-52, respectively.

Then this code returns the value of the bitset interpreted as an IEEE-754 basic binary floating-point object:

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

This does not set all the bits in the NAN (including the sign bit) to match the exact bits in the bitset. There is no portable way to do that; it would typically have to be done by copying the bits into float or double object using memcpy or other copying via a character type, and it requires that the C++ implementation be using a float or double type that is IEEE-754. And, of course, the above requires that the C++ implementation support NAN and INFINITY, and that the the floating-point type in the C++ implementation be capable of representing the value.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
0

First off, one does not simply represent a IEEE 754 floating point. There is a lot that goes into such a representation. Let's say that you're given a bitset variable: param and you want to convert it to a float. To guarantee this is a valid conversion you'll need to ensure:

  • param.size() == sizeof(float) * CHAR_BIT
  • The endianness from which param was encoded matches endian::native
  • numeric_limits<float>::is_iec559 is true
  • The radix with which param was encoded matches numeric_limits<float>::radix

If all these are true then effectively these bits are in the format of your internal floating point representation, and you can convert with a simple function like this (provided that sizeof(unsigned long) == sizeof(float) and 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;
}
SirGuy
  • 10,660
  • 2
  • 36
  • 66
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • `is_iec559` is not a generally useful indicator. `is_iec559` should be true if the type, including arithmetic and other behaviors, conforms to IEC 60559/IEEE 754. However, many C++ implementations use IEEE-754 formats but do not conform to its arithmetic requirements and hence do not set `is_iec559`. So `is_iec559` is not useful as an indicator of whether an IEEE-754 format is in use. – Eric Postpischil Oct 03 '18 at 15:25
  • @EricPostpischil Yeah... the key point though is that floating points which are *not* IEEE 754 *never* set this though. I was going to work through demonstrating how you could extract the bits to reformulate a floating point that was not IEEE 754 compliant... but then I realized probably no one will ever look at this answer so there's little reason to expand it beyond the most simplistic use case. – Jonathan Mee Oct 03 '18 at 15:37