2
\$\begingroup\$

I use this converter to convert a 32-bit binary number to a floating point number. I first find the hexadecimal of the 32-bit binary number and convert to decimal by using the converter.

In my case the 32-bit binary number is: 11001010110010001101011010011001

This is CAC8D699 in hexadecimal.

Below shows this example conversion:

enter image description here

The result is -6581068.5.

I can understand how the sign and the exponent is calculated. But I tried to learn how the mantissa is calculated and could not find a clear explanation.

How is the 23-bit mantissa section i.e. 00110001110001110111000 converted to 1.5690490 in this case?

\$\endgroup\$
  • \$\begingroup\$ The website is rather naive (or sloppy) in referring to "a floating point number". There are many formats. I assume the are using IEEE 745 format and rules. I suggest you use Wikipedia it has a very big section on floating point representation. Much more then we can explain here to you. \$\endgroup\$ – Oldfart Apr 25 '18 at 9:50
  • \$\begingroup\$ Preface it by the "hidden bit" unless the exponent is 0. \$\endgroup\$ – Brian Drummond Apr 25 '18 at 9:53
  • \$\begingroup\$ This is very confusing, where do you even get 00110001110001110111000 from? It's not in the original number you pasted. \$\endgroup\$ – pipe Apr 25 '18 at 10:57
3
\$\begingroup\$

In order to keep this answer short, I'll answer for how it would work for a 8 bit floating point number and a 8 bit fixed point number. I don't actually know how it's usually done, so this will be how I'd do it if I was given this question on an exam.


The floating point number will have the following bits:

\$[~s~|~e_2~|~e_1~|~e_0~|~f_3~|~f_2~|~f_1~|~f_0~]\$

where:

  • s = sign
  • e = exponent\$-3\$
  • f = fraction(mantissa/significand)

A short example:

\$[~0~|~110~|~1001~]=+~|~2^{6-3}~|~1.1001=1.5625×2^3=12.5\$ \$[~0~|~001~|~0011~]=+~|~2^{1-3}~|~1.0011=1.1875×2^{-2}=0.296875\$ \$[~1~|~100~|~1000~]=-~|~2^{4-3}~|~1.1000=-1.5×2^{1}=-3\$ \$[~1~|~000~|~0000~]=-~|~2^{0-3}~|~1.0000=-1×2^{-3}=-0.125\$


The fixed point number will have the following bits:

\$[~s~|~d_3~|~d_2~|~d_1~|~d_0~|~d_{-1}~|~d_{-2}~|~d_{-3}~]\$

where:

  • s = \$-16\$
  • d = number \$×~2^{-3}\$

A short example:

\$[~0~|~0000001~]=0~|~+0000.001=0.125\$
\$[~0~|~1111000~]=0~|~+1111.000=15\$
\$[~1~|~0000001~]=-16~|~+0000.001=-14.875\$
\$[~1~|~1111000~]=-16~|~+1111.000=-1\$

In the computer, 0.125 will be stored as "00000001", but its binary value is 0000.001, so do not confuse yourself with the decimal point. It's still in the same byte. 8 bits.


So let's convert from fixed format to float. Remember, this is Harry's way (that's me).

Here's some important things to focus on:

  • The fractional bits represents values between 0 and 1, then 1 is added to this. So the resulting fraction lies between 1 and 2.
  • A multiplication by 2 is the same as a left shift by 1
  • A division by 2 is the same as a right shift by 1

So here's some pseudo code I came up with that should convert it correctly for positive values. With few edits it can cover zero and negative numbers too.

float8 fixed_to_float(fixed8 a){

  float8 b; //float8 doesn't exist. It's my custom one, SEEEFFFF.
  fixed8 e = 3;//fixed8 doesn't exist, but imagine a int8 where 16 means 1.
  while(a>=2){
    a>>=1;
    //divide "a" by a factor two until
    //it is less than 2
    e++;
    //count the number of right shifts
  }

  while(a<1){
    a<<=1;
    //multiply "a" by a factor two until
    //it is greater than or equal to 1
    e--;
    //count the number of right shifts
    }
  }

  a-=1;
  //remove the "1" from 1.125 and keep the 0.125
  e<<=4;
  //move it into the right position for the floating point representation
  b=e||a;
  //logical OR e and a together.

  return b;
}

For this code to work, the data type "fixed" has to be custom made with the "<" operator so 0000.1111 registers as 0.9375 (15/16) which is less than 1. Or you try to make the value to lie between 32 and 16 rather than 2 and 1.

Pseudo code for fixed to floating in action:

a=\$4.5=100.1 =[~0~|~100100~]\$
e=\$3\$

\$100.100_2\$ is greater than or equal to \$010.000_2\$, add 1 to e (e=\$100_2\$)
\$010.010_2\$ is greater than or equal to \$010.000_2\$, add 1 to e (e=\$101_2\$)
\$001.001_2\$ is less than \$010.000_2\$, stop


a-=\$1=00000010_2\$
e<<\$=4=01010000_2\$


\$ a=~00000010_2\\ e=~01010000_2~OR\\ \overline{b=~01010010_2} \$

Verification:

\$[~0~|~101~|~0010~]=+~|~2^{5-3}~|~1.0010=1.125×2^2=4.5\$


I'll stop here since the question was how to go from fixed to floating point. But I'm technically showing how the conversion is made at the top of this answer with the floating point examples.

\$\endgroup\$
  • \$\begingroup\$ “In order to keep this answer short” - you call this short? (+1) \$\endgroup\$ – Blair Fonville Apr 25 '18 at 16:14
  • 1
    \$\begingroup\$ @BlairFonville Maybe edible is the right word, at least it's easier to absorb, I hope. I could've used more bits, but I don't think it would've been as easy to understand. The point is the same for 8 bit and 32/64 bit. \$\endgroup\$ – Harry Svensson Apr 25 '18 at 16:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.