Search code examples
cfloating-pointbit

Why 1's complement of float variable is not appropriate?


I am writing a simple function to check the 1's compliment of a floating number. This is the code I have written to verify the value:

#include <stdio.h>
#include <stdint.h>

int main()
{
 float input = 25.456;
 printf("input val = %f\n",input);
 uint32_t temp = (uint32_t)input;
 uint32_t toggleval = ~temp;
 
 uint32_t checker = ~toggleval;
 float output = (float)checker;
 printf("output val = %f\n",output);

 return 0;
}

After running this code, I can see the output as

input val = 25.455999
output val = 25.000000

Why are those decimal places different? I am expecting the same values as the input float value? Anything wrong here?


Solution

  • Your attempts at "type-punning" don't do what you think. The uint32_t temp = (uint32_t)input assignment does not return the binary representation of the float as a unit32_t; rather, it converts the value of the float to an unsigned integer (by truncation of the non-integral part). The other cast (back to a float) does a similar (but reversed) conversion.

    For such type-punning (in C but not in C++) you can use a union that has a float and a uint32_t occupying the same memory; then, you can write to one and read from the other:

    #include <stdio.h>
    #include <stdint.h>
    
    int main()
    {
        union { float f; uint32_t u; } pun;
        float input = 25.456f;
        printf("input val = %f\n", input);
    
        pun.f = input; // Write the float part ...
        uint32_t temp = pun.u; // ... but read as a unit32_t
        uint32_t toggleval = ~temp;
    
        uint32_t checker = ~toggleval;
        pun.u = checker; // Write the unit32_t ...
        float output = pun.f; // ... but read as a float
        printf("output val = %f\n", output);
    
        return 0;
    }
    

    Related reading: Unions and type-punning