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