Convert int to float: how it is done

23,090

Solution 1

It is an effort-taking job, but any CPU that has floating-point support will provide an instruction that does it.

If you had to convert a 2's complement int to IEEE float format for yourself, you would:

  • take the integer base-2 log (closely related to the index of the highest set bit), which gives you the exponent. Offset this and store it in the exponent bits of the float.
  • copy the top n bits of the int (starting from the bit after the first set non-sign bit) into the significand of the float. n is however many bits of significand there are in a float (23 for a 32 bit single-precision float). If there are any remaining bits in the int (that is, if it's greater than 224), and the next bit after the ones you have room for is 1, you may or may not round up depending on the IEEE rounding mode in operation.
  • copy the sign bit from the int to the float.

Solution 2

If you look at the assembly

    int i = 5;
000D139E  mov         dword ptr [i],5  
    float f = i;
000D13A5  fild        dword ptr [i]  
000D13A8  fstp        dword ptr [f]  

fild is what does the magic

Solution 3

convert int bits to float

float IntBitsToFloat(long long int bits)
{
    int sign     = ((bits & 0x80000000) == 0) ? 1 : -1;
    int exponent = ((bits & 0x7f800000) >> 23);
    int mantissa =  (bits & 0x007fffff);

    mantissa |= 0x00800000;
   // Calculate the result:
   float f = (float)(sign * mantissa * Power(2, exponent-150));
   return f;
}

Solution 4

On the IA32 systems, the compiler would generate the following:-

fild dword ptr [i] ; load integer in FPU register, I believe all 32bit integers can be represented exactly in an FPU register
fstp dword ptr [f] ; store fpu register to RAM, truncating/rounding to 32 bits, so the value may not be the same as i

Solution 5

Well, I just compiled the code in question under VC++ and looked at the disassembly:

   int i = 5;
00A613BE  mov         dword ptr [i],5 

   float f = i;
00A613C5  fild        dword ptr [i] 
00A613C8  fstp        dword ptr [f] 

First assembly statement moves 5 into the memory represented by i. Second statement, fild, converts the memory represented by i into a floating point number and pushes it onto the FPU stack. The third statement, fstp, takes the memory on the FPU stack and moves it to f.

Share:
23,090
Xu Hong
Author by

Xu Hong

I am always learning.

Updated on April 11, 2020

Comments

  • Xu Hong
    Xu Hong about 4 years

    I'm new to C programming language, and I'd like to ask a question.

    Integer i here is casting to float then f (somehow) successfully represents 5.0:

    int i = 5;
    float f = i;   //Something happened here...
    

    However if we try this approach:

    int i = 5;
    float f = *(float *)&i;
    

    f would NOT get 5.0 since it interprets the bits stored in i in "float's way". So what magic the complier actually does in the first case? It seems a quite effort-taking job... Can someone specify that? Thanks.

  • Ed Heal
    Ed Heal almost 12 years
    That is fine for the mantissa, you need to add that the exponent needs to be computed
  • Sebastian Mach
    Sebastian Mach almost 12 years
    how about explaining it a little bit? mention what this code does and I guarantee at least one upvote :)
  • Sebastian Mach
    Sebastian Mach almost 12 years
    it pragmatically answers the question what magic the complier actually does with a good link, +1.
  • Joseph Willcoxson
    Joseph Willcoxson almost 12 years
    First assembly statement moves 5 into the memory represented by i. Second statement, fild, converts the memory represented by i into a floating point number and pushes it onto the FPU stack. The third statement, fstp, takes the memory on the FPU stack and moves it to f.
  • Sebastian Mach
    Sebastian Mach almost 12 years
    +1 for the comment, but how about adding this information to your answer?