How to print out each bit of a floating point number? - c

I am trying to print out each bit of a floating point number in C.
I am able to do it 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 wouldn't compile if I replaced 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 my whole 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;
}

Thanks to Pascal Cuoq for his comment. I finally figure out how to solve my own problem. Yes, just assign address of the float number to a pointer to integer then dereference 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;
}

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

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);
}
A note on float parameters
Be sure you have the prototype for fpp() in scope when you call it or you will invoke an obscure K&R C vs ANSI C issue.
Update: binary output...
while (n > 0) {
int q;
--n;
for(q = 0x80; q; q >>= 1)
printf("%x", !!(t[n] & q));
}

The following code assumes floats and pointers are the same size, which is true on many systems:
float myfloat = 254940.4394f;
printf("0x%p", *(void**)(&myfloat));

In C language, the term "bit" refers to an element of binary positional representation of a number. Integral numbers in C use binary positional representation, which is why they have "bits". These are the bits you "see" by means of bitwise operators (logical and shifts). Floating-point numbers do not use that representation. Moreover, representation of floating-point numbers is not defined by the language specification, In other words, floating-point numbers in C do not have "bits", which is why you won't be able to access any of their "bits" by any legal means of the language, and which is why you can't apply any bitwise operators to floating-point objects.
Having said that, I'd suspect that you might be interested in physical bits representing a 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 bits of each of the unsigned char objects. That will give you the map of all physical bits representing the object.
However, this won't be exactly equivalent to what you have in your code above. Your code above prints the bits of value representation of an integral object (i.e it is the logical bits I described above), while the memory reinterpretation approach will give you the bits of the object representation (i.e. the physical bits). But then again, floating-point numbers in C don't have logical bits by definition.
Added later: I feel that understanding the difference between the concepts of physical and logical bits might not be an easy task for some readers. As another example that might help to promote the understanding, I'd like to note that there's absolutely nothing that would preclude a perfectly compliant C implementation on ternary hardware, i.e. hardware that does not have physical binary bits at all. In such implementation bitwise operations would still work perfectly fine, they would still access binary bits, i.e. elements of [now only imaginary] binary positional representation of each integral number. That would be the logical bits I'm talking about above.

While from comments it seems that outputing the bits of the internal representation may be what was wanted, here is code to do what the question seemed to literally ask for, without the lossy conversion to int some have proposed:
Outputing a floating point number in binary:
#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;
}

If you want to use your bit_return function on a float, you can just cheat:
float f = 42.69;
for ....
bit_return((int) f, loc)
The (int) cast will make the compiler believe you're working with an integer, so bit_return will work.
This is essentially what Pascal was suggesting.
EDIT:
I stand corrected by Pascal. I think this will conform with his latest comment:
bit_return (*((float *) &f), loc)
hope I got it right that time.
Another alternative (with fewer parentheses) would be to use a union to cheat on the data type.

I have included code which produces hexadecimal output that I think may 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)
From my code example below, it should become obvious to you how to output the bits. Cast the double's address to unsigned char * and output the bits of sizeof(double) chars.
Since I want to output the exponent and significand (and sign bit) of a floating-point number, my example code digs into the bits of the IEEE-754 standard representation for 64-bit 'double precision' floating pointing point in radix 2. Therefore I do not use sizeof(double) other than to verify that the compiler and I agree that double means a 64-bit float.
If you would like to output the bits for a floating-point number of any type, do use sizeof(double) rather than 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) << 4) + ((((char *)&(dbl))[6] & 0xF0) >> 4) & 0x7FF) - 0x3FF;
// Copy the 52-bit significand to an integer we will later display
for (i = 0; i < 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) >> 32),
(DWORD)(ll & 0xFFFFFFFFLL),
exponent);
}
Nota Bene: The significand is displayed as a hexadecimal fraction ("0x1.24B0D0FA40000") and the exponent is display as decimal ("40"). For me, this was an intuitive way to display the floating-point bits.

Print the integer part, then a '.', then the fractional part.
float f = ...
int int_part = floor(f)
int fraction_part = floor((f - int_part) * pow(2.0, 32))
You can then use your bit_return to print x and y. Bonus points for not printing leading and/or trailing zeros.

I think the best way to address this question is to use an union
unsigned f2u(float f)
{
union floatToUnsiged{
float a;
unsigned b;
}test;
test.a = f;
return (test.b);
}

Related

What does 0x7fff mean? C language

I've made function that prints memory address to the stdout but it dosent work the sameway as printf("%p", ...). For example the printf gives me this: 0x7fff58a2d2bb but my function prints something like this: 58a2d2bb. I know what 0x mean but cant get what 7fff mean. Can someone explain me what does that part mean and how can I add it to my code:
char *ft_itoa_base(uintmax_t num, uintmax_t base){
int i;
uintmax_t val_cp;
uintmax_t rem;
char *str;
val_cp = num;
i = 1;
while((val_cp /= base) >= 1)
i++;
str = ft_strnew(i); // Basically what it does (char*)malloc(sizeof(char) * (i + 1))
str[i] = '\0';
while(i-- > 0)
{
rem = num % base;
str[i] = (rem > 9)? (rem-10) + 'a' : rem + '0';
num /= base;
}
return (str);}
char a = 'x';
void* p0 = &a;
uintmax_t i = (uintmax_t)p0;
ft_putstr(ft_itoa_base(i, 16));
ft_putchar('\n');
printf("PrintF: %p", p0);
What does 0x7fff mean?
The missing "0x7fff" is part of the correct hexadecimal address lost in errant code of ft_itoa_base().
OP's original ft_itoa_base() was not fully uintmax_t ready given one of the variables was int instead of uintmax_t.
That caused the output to print a truncated address of "58a2d2bb" rather than the correct "7fff58a2d2bb".
The posted corrected ft_itoa_base() has minor weaknesses.
// char* ft_itoa_base(uintmax_t num, uintmax_t base) {
// No need for base to be so wide with uintmax_t
char* ft_itoa_base(uintmax_t num, int /* or unsigned */ base) {
int i;
uintmax_t val_cp;
// uintmax_t rem;
// No need for rem to be so wide with uintmax_t
int /* or unsigned */ rem;
char *str;
...
0x7fff58a2d2bb is 140,734,680,453,819 expressed in hexadecimal (or base 16) format where the digit a represents 10, b represents 11, and up to f which represents 15.
Base 16 or hexadecimal format is preferred over base 10 for memory addresses because 16 is a power of 2 which makes it handy for viewing as bit masks, and 10 is not which makes it difficult to view in terms of bit masks.

issue convert double range number to binary

I have a problem to convert integer type's double rage number to binary as the below,
void intToBin(int digit) {
int b;
int k = 0;
char *bits;
int i;
bits= (char *) malloc(sizeof(char));
while (digit) {
b = digit % 2;
digit = digit / 2;
bits[k] = b;
k++;
}
for ( i = k - 1; i >= 0; i--) {
printf("%d", bits[i]);
}
}
But as you can see the that function's arguments input is integer.
I came across the error when I tried with intToBin(10329216702565230)
because 10329216702565230 is over integer range.
How can I extend what that have integer type's double rage number to binary ?
update
I've updated the below code
void intToBin(uint64_t digit) {
int b;
int k = 0;
char *bits;
int i;
bits = malloc(sizeof digit * 64);
while (digit) {
b = digit % 2;
digit = digit / 2;
bits[k] = b;
k++;
}
for ( i = k - 1; i >= 0; i--) {
printf("%d", bits[i]);
}
}
But I didn't get it what should I do to get the 2's complement ?
m
dmnngn
Solution is to use type which supports that range of numbers.
Use unsigned long long or uint64_t(assuming you are passing non negative integers, otherwise use long long or int64_t). Then you call the function like this Edited to add int64_t to uint64_t from the comment posted. unsigned long long is 64 bits atleast - can even be wider. With OP's comment of getting 64 bits output - better to use (u)int64_t
intToBin(10329216702565230U)
In case you want to use negative numbers use long long.Call it like this
intToBin(10329216702565230L).
You didn't allocate enough memory - you were accessing memory that you haven't allocated, resulting in Undefined behavior. You have allocated 1 char first and then you didn't allocate. You can solve this by reallocating - reallocate memory inside the loop (reallocate 1 char at a time inside loop). And then use it. Instead of calling realloc multiple times why don't you allocate memory for 64 chars and then use it to store the result. And in the end, the left over space can be freed with another realloc call.
You don't need to cast the return value of malloc (void* to char* conversion is done implicitly).
You didn't check the return value of malloc. malloc may return NULL and in that case you have to handle that separately. For example:-
#define NBITS 64
...
...
bits = malloc(NBITS);
if( bits == NULL ){
perror("malloc failed");
exit(EXIT_FAILURE);
}
Note: The 64 magic number is coming introduced with the thought that unsigned long long is 64 bits atleast. So while converting we will be using that in case the number of bits exceeds 64 we will reallocate. A better choice is to use what chux said - sizeof digit * CHAR_BIT.
Also
bits[k] = b+'0';
We are putting the ascii value and then you can print it like this
printf("%c", bits[i]);
You forgot to free the allocated memory. Without freeing it (free(bits)), you have memory leak.
Davic C. Rankins comment
void intToBin(int digit)
{
int b;
int k = 0;
char *bits;
int i;
bits= (char *) malloc(sizeof(char));
while (digit) {
b = digit % 2;
digit = digit / 2;
bits[k] = b;
k++;
}
for ( i = k - 1; i >= 0; i--) {
printf("%d", bits[i]);
}
}
The answer is simple,
Replace int with int64_t to use 64 bits instead of 32.
Please try it and let us know
Replace int with int64_t to use 64 bits instead of 32.

can I get the 2s complement representation of integer from register?

I think if some integer is in register by scanf, then the number would be in 2s complement representation. Can I get that number by printf? I searched many websites but couldnt find the code for C beginners...
Float numbers are not stored in 2's complement, but rather in IEEE 754. To print the binary representation of some binary data, first see https://stackoverflow.com/a/112956/1689451. You can put your float into a union to extract the single bytes:
#include <stdio.h> /* printf */
#include <string.h> /* strcat */
// taken from https://stackoverflow.com/a/112956/1689451
const char *byte_to_binary(int x)
{
static char b[9];
b[0] = '\0';
int z;
for (z = 128; z > 0; z >>= 1)
{
strcat(b, ((x & z) == z) ? "1" : "0");
}
return b;
}
union {
float f;
unsigned char b[4];
} x;
x.f = 0.34;
for (int i = 0; i < 4; i++) {
printf("%s", byte_to_binary(x.b[i]));
}
I did not try the example; does probably not compile, but should give hints in the right direction.
There's no standard in c that prints "two's complement" number or binary numbers in general, if that's your question. That task must be solved separately. Eg.
for (i=0;i<32;i++) putc( '0'+((number >> (31-i)) & 1)); // or copy to local strings
Otherwise scanf("%f", &my_float); prints with printf("%f", my_float);

How to convert floating value to integer with exact precision like 123.3443 to 1233443?

Sample code:
int main() {
float f = 123.542;
int i = (int)f;
printf("%d\n",i);
}
123.3443 can't be exactly represented by a floating-point number -- in a 32-bit float, it's effectively represented as 16166984 / 131072, which is actually 123.34429931640625, not 123.3443. (It's off by around 6.8 x 10^-7.)
If this is really the result you want (which it's probably not), take a look at how IEEE-754 floats work, and pull out your favorite arbitrary-precision math suite. Once you understand what's going on "behind the scenes", generating an exact representation shouldn't be too hard. Generating a "close enough" rounded representation is actually much harder. :)
int i = (int) (f * 10000 + 0.5);
Multiply the float by 10^x where x is how many digits after the decimal you want and then cast to int.
If you don't need to do any repetitive processing of the converted number and are only looking to convert the numbers into an integer, the easiest way is to use sprintf, then sum up the decimals with a for loop using power of 10 rules. If you need "exact precision" for math, use a BCD. The following algorithm will allow you to truncate the number of digits for "exact precision".
#include "math.h"
long ConvertToScaledInteger (float value, int significantDigits = -1)
{
// Note: for 32-bit float, use long return and for double use long long.
if (significantDigits < 1) // Ditch the '-' and the '.'
significantDigits += 2;
else
++significantDigits; // Ditch the '.'
char* floatingPointString = malloc(sizeof (char) * (4 + FLT_MANT_DIG - FLT_MIN_EXP));
/*< This solution is for a 32-bit floating point number. Replace FLT
with DBL, and it will produce the max number of chars in a 64-bit
float string. */
if (significantDigits < 0) //< Then use all of the float's digits.
{
sprintf (floatingPointString , "%f", floatingPointNumber);
}
else //< Then truncate the number of decimal places.
{
char decimalPlaceString[9];
char percentString = "%\0";
sprintf (decimalPlaceString, "%s%if", percentString , significantDigits);
sprintf (floatingPointString , decimalPlaceString, value);
}
int stringLength = strlen (floatingPointString),
index;
long returnValue = 0;
double powerOfTen = 10.0,
currentValue;
// Find if we have an ending of .0, and backtrack.
if (floatingPointString[stringLength - 1] == '0' && floatingPointString[stringLength - 2] == '.')
index = stringLength - 3;
else
index = stringLength - 1;
for (; index > 0; --index)
{
if (floatingPointString[index] == '.')
--index;
// Subtract ASCII '0' converts ASCII to integer.
currentValue = (double) floatingPointString[index] - '0';
returnValue += (long) currentValue * pow (10.0, powerOfTen);
powerOfTen += 1.0;
}
if (floatingPointString[0] == '-')
returnValue *= -1;
return returnValue;
}
The integer equivalent of a float number f
float f=123.456;
can be made using modff() like
float integral, fractional;
char str[50], temp[20];
fractional = modff(f, &integral);
Now integral has the integer part (like 123.000000) and fractional has the fractional part (like 0.456000).
If the floating point number (f in this case) were negative, both integral and fractional would be negative.
You can do
if(fractional<0)
{
fractional = -fractional;
}
to remedy that.
Now,
sprintf(temp, "%g", fractional);
The %g format specifier will remove the trailing zeros and temp will now have "0.456".
sprintf(str, "%g%s", integral, temp[1]=='.'?temp+2:"");
The temp[1]=='.'? is done because if the fractional part were 0, there would'v been no decimal point while printing fractional as it would've been 0 and not 0.000000. If the second character in temp is not ., fractional is zero and we needn't bother with it.
Now in our case, str would be "123456". But that's in the form of a string. We need to convert it into an integer. Use strtol() for that.
long l=strtol(str, NULL, 10);
if(l>INT_MAX || errno==ERANGE)
{
printf("\noverflow");
}
else
{
printf("\n%d", strtol(str, NULL, 10));
}
You may check the return value of strtol() and that of errno (from errno.h. Check whether it is ERANGE ) to see if overflow occurred.
To see if the resultant value can be stored in an int, first store the value returned by strtol() in a long int and see if that is greater than INT_MAX (it's in limits.h).
It should be noted that the accuracy of the result will depend upon the accuracy with which the floating point number is represented in binary.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int f2i(float v, int size, int fsize){
char *buff, *p;
int ret;
buff = malloc(sizeof(char)*(size + 2));
sprintf(buff, "%*.*f", size, fsize, v);
p = strchr(buff, '.');
while(*p=*(p+1))p++;
ret = atoi(buff);
free(buff);
return ret;
}
int main(){
float f = 123.3443;
printf("%d\n", f2i(f, 7, 4));
f=123.542;
printf("%d\n", f2i(f, 6, 3));
return 0;
}

How would you count the number of bits set in a floating point number?

How do you count the number of bits set in a floating point number using C functions?
#include <stdio.h> /* for printf() */
#include <limits.h> /* for CHAR_BIT */
int main(void) {
/* union method */
{
/* a union can only be initialized for the first option in the union */
union { float f; char cs[sizeof(float)]; } const focs = { 1.0 };
int j,k;
int count = 0;
for (j = 0; j < sizeof(float); j++)
{
char const byte = focs.cs[j];
for (k = 0; k < CHAR_BIT; k++)
{
if ((1 << k) & byte)
{
count++;
}
}
}
printf("count(%2.1f) = %d\n", focs.f, count);
}
/* cast method */
{
float const f = 2.5;
int j,k;
int count = 0;
for (j = 0; j < sizeof(float); j++)
{
char const byte = ((char *)&f)[j];
for (k = 0; k < CHAR_BIT; k++)
{
if ((1 << k) & byte)
{
count++;
}
}
}
printf("count(%2.1f) = %d\n", f, count);
}
return 0;
}
If you want to work on the actual bitwise representation of a floating point number, you should do something like this:
float f; /* whatever your float is */
int i = *(int *)&f;
What this does is take the address of f with the address-of operator, &. This address is of type float *, a pointer to a float. Then it recasts it with (int *), which says "pretend this pointer doesn't point to a float anymore, but now it points to an int". Note that it doesn't change the value at f at all. Then the last * (or first, since we read right-to-left) dereferences this pointer, which is a pointer to an int, and therefore returns an int, a.k.a. the integer with the same bitwise representation as the float.
To do the opposite (convert and int i back to a float f), do the opposite:
f = *(float *)&i;
Unless I am mistaken, this operation is undefined by the C standard, but will probably work on most computers and compilers. It is undefined because I believe the actual floating-point representation of numbers is implementation-dependent, and can be left to the CPU or the compiler, and therefore the value of i is almost impossible to predict after this operation (same goes for the value of f in the reverse operation). It is famously used in John Carmack's inverse square root function for the same nefarious purpose.
Anyway, if you're doing this in real code, you should probably stop and think twice about what you're trying to do and why you're using floats to do it. However, if you're just doing this out of curiosity, or you have thought about these and are sure of your design and methods, go for it.
I'm led to believe that you already know how to count the number of bits set in a regular integer, as this is a much easier task. If you don't know, your compiler (or the C language, I don't even know) may have a function to count bits, or you could use something from the wonderful Bit-Twiddling Hacks website, which has ways to do things like this with bitwise operations (which should be pretty fast).
A nice function for counting set bits in an integer mentioned by the first answer:
int NumberOfSetBits(int i)
{
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
return ((i + (i >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
}
To use it on your float you would do something like this:
//...
float f;
//...
int numBitsOfF = NumberOfSetBits(*(int*) &f);
You mean the bits set in the IEEE-754 single precision representation of a number? If so, cast it to int (both float and int are 32bit wide) and do a regular bit count: SO question #109023.
The following function will find the number of bits in a 32-bit number. Just type case your float with integer and call this function by a cast
float f=3.14f;
count_bits(*(int *)&f);
int count_bits(int v)
{
// count the number of bits set in v
int c; // c accumulates the total bits set in v
int b=v;
for (c = 0; v; c++)
{
v &= v - 1; // clear the least significant bit set
}
//printf("No of bits in %d is %d\n",b,c);
return c;
}

Resources