Home > other >  How to represent a floating point number in binary from 32-bit hex value in C without using bitset
How to represent a floating point number in binary from 32-bit hex value in C without using bitset

Time:09-09

Given a 32-bit hex like 0x7f000002, how do I get the full value of this number printed in binary without using bitset or defining any float variables to use union?

I know that it is supposed to display 10000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0 for this particular 32-bit hex number.

But I don't know how to get there without using those 2 aforementioned function/variable.

CodePudding user response:

You can appeal directly to what the bits in a floating point number mean: https://en.wikipedia.org/wiki/Single-precision_floating-point_format

The last 23 bits store the mantissa, and the eight bits before store the biased exponent (with the one bit before that being the signbit). The number is essentially "1.<mantissa> * 2**(<exponent> bias)", and multiplying by a power of two is essentially shifting the binary radix point, or adding zeros to the left or right in the binary string.

Taking all that into account ( edge cases for subnormal numbers and inf and NaN), you can make this function:

std::string floatbits_to_binaryfloatstring(std::uint32_t floatbits) {
    bool signbit = floatbits >> 31;
    int exponent = (floatbits >> 23) & 0xff;
    std::uint32_t fraction = floatbits & 0x7fffffu;

    std::string result;
    result  = signbit ? '-' : ' ';

    if (exponent == 0xff) {
        if (fraction == 0) {
            result  = "inf";
        } else {
            result  = "NaN";
        }
    } else if (exponent == 0) {
        if (fraction == 0) {
            result  = "0.0";
        } else {
            // Subnormal
            result  = "0.";
            result.append(125, '0');
            for (int i = 23; i-- > 0;) {
                result  = (fraction >> i) & 1 ? '1' : '0';
            }
            // Remove trailing zeroes
            result.erase(result.find_last_of('1')   1u, result.npos);
        }
    } else {
        fraction |= 0x800000u;  // Make implicit bit explicit
        exponent -= 127   23;
        // The number is "fraction * 2**(exponent)" in binary
        if (exponent <= -24) {
            result  = "0.";
            result.append(-exponent - 24, '0');
            for (int i = 24; i-- > 0;) {
                result  = (fraction >> i) & 1 ? '1' : '0';
            }
        } else if (exponent >= 0) {
            for (int i = 24; i-- > 0;) {
                result  = (fraction >> i) & 1 ? '1' : '0';
            }
            result.append(exponent, '0');
            result  = '.';
        } else {
            int point = 24   exponent;
            for (int i = 24; i-- > 0;) {
                result  = (fraction >> i) & 1 ? '1' : '0';
                if (--point == 0) result  = '.';
            }
        }
        // Remove trailing zeroes
        result.erase(result.find_last_not_of('0')   1u, result.npos);
        if (result.back() == '.') result  = '0';
    }

    return result;
}

Example: https://wandbox.org/permlink/9jtWfFJeEmTl6i1i

I haven't tested this thoroughly, there might be some mistake somewhere.

Since this is a weird format in the first place, there probably isn't a prebuilt solution for this. hexfloat is close, but in hex and with binary p notation instead

  • Related