Home > Back-end >  Representing float point in hex with printf("%a", 3.14)
Representing float point in hex with printf("%a", 3.14)

Time:11-28

A simple code like this printf("hex representation for %f is [%a]\n", 3.14, 3.14);, I expect the result to be 0x4048f5c3 (full binary version is: 0100 0000 0100 1000 1111 0101 1100 0011, 0x4.8f5c3p-1) according to reference websites below, but the compiled executable shows [0xc.8f5c3p-2] (binary: 1100.1000 1111 0101 1100 0011), why did the C compiler shows exponent as -2 instead of -1?

The compiler setting is:

"command": "c:/msys64/mingw64/bin/gcc.exe",
"args": [
            "-g",               
            "${file}",
            "-o",
            "${fileDirname}\\${fileBasenameNoExtension}.exe",
            "-Wall",
            "-Werror",
            "-std=c11"

Reference: https://users.cs.fiu.edu/~downeyt/cop2400/float.htm https://gregstoll.com/~gregstoll/floattohex/

CodePudding user response:

The website you are using is displaying the binary representation of a floating-point number. For example, 3.14 is 40 48 F5 C3 in big-endian, or C3 F5 48 40 in little-endian.

The hex representation in C is the actual floating-point number in base 16, not it's binary representation. 0xc.8f5c3p-2 means c.8f5c3 * 2^(-2). If we convert this to decimal using the usual conversion algorithm, we get 3.14:

12(C) * 16^0 8 * 16^(-1) 15(F) * 16^(-2) 5 * 16^(-3) 12(C) * 16^(-4) 3 * 16^(-5) = 12 0.5 0.05859 ... = 12.56 (with approximation)

Now multiply by 2^(-2), or divide by 4, and we get 3.14.

The difference between the 2 representations is shown here (note that this program technically causes undefined behavior in C, because of the uint32_t* to float* cast followed by dereference, but in this case the behavior is to use the binary representation to create a floating-point number, as one would expect):

#include <stdio.h>
#include <inttypes.h>

// Assuming IEE-754 representation of 32-bit floats

int main(void)
{
    float x = 0xC.8F5C3p-2;
    uint32_t y = 0x4048F5C3;
    printf("Base-16 representation of %f is: %A\n", x, x);
    printf("Binary representation of %f is: 0X%"PRIX32"\n", *(float*)&y, y);
}

And this is the output I get on my computer:

Base-16 representation of 3.140000 is: 0XC.8F5C3P-2
Binary representation of 3.140000 is: 0X4048F5C3
  • Related