How to print each bit of a floating point number?

I am trying to print every bit of a floating point number in C.

I can do this for integers with this:

int bit_return(int a, int loc) // Bit returned at location { int buf = a & 1<<loc; if (buf == 0) return 0; else return 1; } 

The compiler will not compile if I replace int a with float a .

Is there a solution for this?


Copy and reformat your comment below

Ok, for people who are not clear, I post all my code here:

 #include <stdio.h> #include <stdlib.h> int bit_return(int a, int loc) // Bit returned at location { int buf = a & 1<<loc; if (buf == 0) return 0; else return 1; } int main() { int a = 289642; // Represent 'a' in binary int i = 0; for (i = 31; i>=0; i--) { printf("%d",bit_return(a,i)); } return 0; } 
+4
source share
9 answers

Thanks to Pascal Cuoc for his comment. I’ll finally figure out how to solve my problem. Yes, just assign the address of the floating-point number to a pointer to an integer, and then look for it. Here is my code solution:

 #include <stdio.h> // bit returned at location int bit_return(int a, int loc) { int buf = a & 1<<loc; if (buf == 0) return 0; else return 1; } int main() { //11000010111011010100000000000000 // 1 sign bit | 8 exponent bit | 23 fraction bits float a = -118.625; int *b; b = &a; int i; for (i = 31; i >= 0; i--) { printf("%d",bit_return(*b,i)); } return 0; } 
+5
source

Move the address of your float to an int address of the same size and pass that int to your existing function.

+4
source

In C, the term β€œbit” refers to a binary positional representation of a number. Integral numbers in C use a binary positional representation, so they have a β€œbit”. These are the bits that you see using bitwise operators (logical and shifts). Floating-point numbers do not use this representation. Moreover, the representation of floating-point numbers is not determined by the language specification. In other words, floating-point numbers in C do not have "bit", so you cannot access any of their "bits", by any legal means of the language, and that is why you cannot apply bitwise operators to floating point objects.

Having said that, I suspect that you might be interested in the physical bits representing the floating point object. You can reinterpret the memory occupied by the floating point object (or any other object) as an array of unsigned char elements and print the bit of each of the unsigned char objects. This will give you a map of all the physical bits representing the object.

However, this will not be exactly equivalent to what you have in your code above. Your code above prints the bits representing the value of an integer object (i.e., these are the logical bits that I described above), while the memory reinterpretation routine will give you bits representing the object (i.e. physical bits). But then again, floating point numbers in C do not have logical bits by definition.

Added later: I feel that understanding the differences between the concepts of physical and logical bits can be a daunting task for some readers. As another example that can help advance understanding, I would like to point out that there’s absolutely nothing that could exclude a fully compatible implementation of C on tri-core hardware, that is, hardware that does not have physical binary bits at all. In such an implementation, bitwise operations will still work fine, they will still access the binary bits, that is, the elements of the [now only imaginary] binary positional representation of each integer. These will be the logical bits of which I speak above.

+3
source
 static void printme(void *c, size_t n) { unsigned char *t = c; if (c == NULL) return; while (n > 0) { --n; printf("%02x", t[n]); } printf("\n"); } void fpp(float f, double d) { printme(&f, sizeof f); printme(&d, sizeof d); } 
  • Note on float options

    Make sure you have a prototype for fpp() in the area when you call it, or you will cause an incomprehensible K & RC vs ANSI C.

Update: binary output ...

  while (n > 0) { int q; --n; for(q = 0x80; q; q >>= 1) printf("%x", !!(t[n] & q)); } 
+3
source

While it seems from the comments that the output of the binary data of the internal representation may be what you need, here is the code that should do what it seemed to literally ask the question, without converting losses to int, some suggested:

Binary floating point output:

 #include <stdio.h> #include <stdlib.h> void output_binary_fp_number(double arg) { double pow2; if ( arg < 0 ) { putchar('-'); arg = -arg; } if ( arg - arg != 0 ) { printf("Inf"); } else { /* compare and subtract descending powers of two, printing a binary digit for each */ /* first figure out where to start */ for ( pow2 = 1; pow2 * 2 <= arg; pow2 *= 2 ) ; while ( arg != 0 || pow2 >= 1 ) { if ( pow2 == .5 ) putchar('.'); if ( arg < pow2 ) putchar('0'); else { putchar('1'); arg -= pow2; } pow2 *= .5; } } putchar('\n'); return; } void usage(char *progname) { fprintf(stderr, "Usage: %s real-number\n", progname); exit(EXIT_FAILURE); } int main(int argc, char **argv) { double arg; char *endp; if ( argc != 2 ) usage(argv[0]); arg = strtod(argv[1], &endp); if ( endp == argv[1] || *endp ) usage(argv[0]); output_binary_fp_number(arg); return EXIT_SUCCESS; } 
+2
source

If you want to use the bit_return function on a float, you can simply cheat:

 float f = 42.69; for .... bit_return((int) f, loc) 

The cast (int) will make the compiler sure that you are working with an integer, so bit_return will work.

This is essentially what Pascal suggested.

EDIT:

I am corrected by Pascal. I think this will be consistent with his last comment:

 bit_return (*((float *) &f), loc) 

I hope I understood this time correctly.

Another alternative (with fewer parentheses) would be to use union to cheat on a data type.

+1
source

The following code assumes that float and pointers are the same size, which is true for many systems:

 float myfloat = 254940.4394f; printf("0x%p", *(void**)(&myfloat)); 
+1
source

I included code that generates hexadecimal output, which I think can help you understand floating point numbers. Here is an example:

double: 00 00 A4 0F 0D 4B 72 42 (1257096936000.000000) (+ 0x1.24B0D0FA40000 x 2 ^ 40)

In my code example below, it should be obvious to you how to output the bits. Move the double address to unsigned char * and output the sizeof(double) bit.

Since I want to output the exponent and the significant (and sign bit) floating-point numbers, my sample code delves into the bits of the standard IEEE-754 representation for a 64-bit double-precision floating-point in radix 2. Therefore, I do not use sizeof(double) , except to verify that the compiler and I agree that double means a 64-bit float.

If you want to output bits for a floating point number of any type, use sizeof(double) , not 8 .

 void hexdump_ieee754_double_x86(double dbl) { LONGLONG ll = 0; char * pch = (char *)&ll; int i; int exponent = 0; assert(8 == sizeof(dbl)); // Extract the 11-bit exponent, and apply the 'bias' of 0x3FF. exponent = (((((char *)&(dbl))[7] & 0x7F) &lt;&lt; 4) + ((((char *)&(dbl))[6] & 0xF0) &gt;&gt; 4) & 0x7FF) - 0x3FF; // Copy the 52-bit significand to an integer we will later display for (i = 0; i &lt; 6; i ++) *pch++ = ((char *)&(dbl))[i]; *pch++ = ((char *)&(dbl))[6] & 0xF; printf("double: %02X %02X %02X %02X %02X %02X %02X %02X (%f)", ((unsigned char *)&(dbl))[0], ((unsigned char *)&(dbl))[1], ((unsigned char *)&(dbl))[2], ((unsigned char *)&(dbl))[3], ((unsigned char *)&(dbl))[4], ((unsigned char *)&(dbl))[5], ((unsigned char *)&(dbl))[6], ((unsigned char *)&(dbl))[7], dbl); printf( "\t(%c0x1.%05X%08X x 2^%d)\n", (((char *)&(dbl))[6] & 0x80) ? '-' : '+', (DWORD)((ll & 0xFFFFFFFF00000000LL) &gt;&gt; 32), (DWORD)(ll & 0xFFFFFFFFLL), exponent); } 

Nota Bene: the value is displayed as a hexadecimal fraction ("0x1.24B0D0FA40000"), and the exponent is displayed as a decimal ("40"). For me, it was an intuitive way to display floating point bits.

+1
source

Print the integer part, then the ".", Then the fractional part.

 float f = ... int int_part = floor(f) int fraction_part = floor((f - int_part) * pow(2.0, 32)) 

Then you can use bit_return to print x and y. Bonus points for not printing leading and / or trailing zeros.

0
source

All Articles