Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

how to convert float to binary 2

Status
Not open for further replies.

qkslvrwolf

Programmer
Jul 9, 2002
28
0
0
US
Ok, this one is a little bit over my head...I've had it explained by my prof, but am still a little fuzzy. Can anyone give me an algorithm for this? Preferably with a non-code explanation?
 
I couldn't help myself; had to code something.. :)

this is one solution that does the trick:

int main() {

float num = 236.63568;
char res[sizeof(float)*8+1]; // Where the result will go..

int *p;
int i=0;

unsigned int mask=0x80000000; // binary this is 1000000..

p=# // have to use an int pointer because you can't
// do AND on a float

while(mask) {
res[i++]=(*p & mask) ? '1' : '0';
mask>>=1;
}
res=0; // terminate the string

printf("%s\n", res);

}

(This assumes that float and int are of the same length (bits), like on x86 CC)


The thing we have to do is to read the float bit by bit somehow. I use a mask that contains a 1 in the leftmost position from the start. Then I use bitwise AND to see if the position in num corresponding to the mask is a 1.
(*p & mask) is 0 if the bit is 0.

At the end of the loop the mask is right shifted to move on to the next position. At the end when the 1 has moved all the way to the rightmost position it is shifted out and mask will contain 0 and the while will terminate.

As I do all this I save the bits in the string res along the way.
 
Hmm, extanuel hijacked my computer so he could get his answer in first. ;)
It's a very elegant solution, but you can only use it on floats. I devised a solution that can be used on any object what so ever, as long as you can use sizeof() on it =)

Here it goes:
#define STRING_LENGTH sizeof(float)*8

float num = -5e1;
int i = 0, res_i = STRING_LENGTH-1;
char *p = (char *)#
char bin[STRING_LENGTH+1];

bin[STRING_LENGTH] = '\0';

for (i = 0; i < sizeof(float); i++) {
char tmp = p;
int j = 0;

for (j = 0; j < 8; j++) {
bin[res_i--] = '0' + (tmp & 1);
tmp >>= 1;
}
}


The explanation:
First off we save a char-pointer (so that we can step byte by byte) to the start of the float. Then we step through the floats binary data byte by byte, we only have to be aware that x86 machines are little endian, meaning the smallest byte is saved first. Because of this we step through the float from left to right and the result string right to left...man, this would have been so much nicer on a big-endian machine ;)

In the inner loop we step through 8 times and examine each bit in each step of the iteration.

&quot;tmp & 1&quot; gives the value of the lowest bit. '0' + 1 == '1'.
&quot;tmp >>= 1;&quot; shifts the content of tmp one step to the right (same thing as dividing tmp with 2).

Hope it brought, at least some, clarity =)
 
Thank you both. The explanations were both wonderfully helpful, and it seems to work. Two questions though. First, when you do res[i++], does this increment i after it uses i as an index? I'm assuming thats the case, otherwise, you would have to have initialized i to -1. Second, when I run (my slight modification of) this program (I used extanual's after a coin toss) on 3.14, I get 01000000010010001111010111000011
which, while I could use an explanation of binary representations of floats, just doesn't look right. Is it? (Anyone want to post and explanation of the binary reprensation of floats? ;) ;) )
 
It works like this:

i++ : return a copy of i's value _before_ anything is modified, then increase i.
++i : increase i and then return the value it will have _after_ it is increased.

I believe that the representation (according to the IEEE standard of single precision floating point numbers) is something like:
1 bit sign (0 == positive, 1 == negative), 23 bits mantissa (the 3.14-part of the number), I don't know the exact format of this, I think it's some kind of balanced representation or something weird of that sort, then 8 bits exponent, this might also be some weird representation.

I can check up on this and get back to you with a correct answer later if you like.

Happy hacking.
 
Cool. Didn't know you could to ++i. Thanks!

As to whether you explain the binary rep of floats, I'd sure appreciate it, but its your time. I'm already grateful for all the help you've given!

sean
 
Ey, no prb, I find this is interesting to =)

Ok, I checked it out, it seems it's like this (IEEE Basic Single precision floating point):

+-+--------+-----------------------+
|s | e | f | = v
+-+--------+-----------------------+
0 1 8 31

Where s is a 1 bit sign, e is an 8 bit exponent and f is a 23 bit number.
It is interprated like this:
There are 5 cases (v is the number this is all representing):
a: v == NaN (Not-a-Number) if e == 255 and f != 0
b: v == (-1)^s * infinity if e == 255 and f == 0
c: v == (-1)^s * (1.f)*2^(e-127) if 0 < e < 255 (normal case)
d: v == (-1)^s * (0.f)*2^-126 if e == 0 and f != 0
e: v == (-1)^s * 0 if e == 0 and f == 0

So your 01000000 01001000 11110101 11000011 would be:
(-1)^0 * 1.57000005245208740234375*2^(129-127) = 3.140000105
=P

Remember that in 1.f above, f is in binary, so in your case it's 1.10010001111010111000011 and then you have to convert that to decimal ( == 1.57000005245208740234375).
 
Sorry, the 129 in the exponent is supposed to be 128, type-o =)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top