To convert a float / double to its IEEE754 representation in C++

Viewed 594

Trying to figure out how this works but I cannot wrap my head around what i is representing. I understand that we assign an unsigned long long because it contains the same number of bits as a float. But what exactly does i stand for?

My best interpretation is that we are trying to cast the double number to an unsigned long long int because they have the same number of bits. And it appears that the best way to do so is to dereference the pointer we have set up?

Any help will be greatly appreciated!

void printDouble(double d) {

unsigned long long int i = *(unsigned long long int *)&d;

for (int j = 63; j >= 0; j--) {
    std::cout << ((i >> j) & 1);

    if (j == 63) std::cout << " ";
    else if (j == 52) std::cout << " ";
}

}

1 Answers

On most (but not all) platforms, float and double use IEEE 754 representation to approximate real valued numbers. For the meaning of the bits, see e.g. https://en.wikipedia.org/wiki/IEEE_754. Briefly, in an IEEE-754 64-bit double, there is a sign bit, an 11-bit exponent, and a 52-bit significand (aka mantissa) to represent the real number in a form like

sign ⋅ 2^(exponent − 1023) ⋅ (1.0 + significand / 2^52)

There are special cases beyond this (infinities, NaN, subnormals, signed zeros), but that's the essential idea. If you are looking for a deeper reference, a great book is Michael L. Overton, "Numerical Computing with IEEE Floating Point Arithmetic".

Beware that dereferencing *(unsigned long long int *)&d is undefined behavior, as others have commented. If you really want to get the bits of a double into a 64-bit int, a safe way to do that is through memcpy:

uint64_t bits;
std::memcpy(&bits, &d, sizeof(d));
Related