简体   繁体   中英

How to represent a floating point number in binary from 32-bit hex value in C++ without using bitset or float variable?

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM