简体   繁体   中英

Convert int to float: how it is done

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.

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 2 24 ), 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 .

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

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;
}

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

The magic depends on your platform.

One possibility is that your CPU has a special instruction to copy floating point numbers into integral registers.

Of course someone has to design these CPUs, so this is not really an explanation for the algorithm at hand.

A platform might be using a floating point format that goes like this (actually, this is a fixed-point format for the sake of example):

[sIIIIFFFF]

where s is the sign, the I s are the part before the dot, the F s are the part after the dot, eg (dot is virtual and only for presentation)

 -  47.5000
[sIIII.FFFF]

in this case conversion is almost trivial and can be implemented using bitshifting:

    -47.5000
 >> 4
 ---------------
    -47

And like in this example, commodity C++ implementations use a floating point representation often referred to as IEEE Floating Point , see also IEEE 754-1985 . These are more complicated than fixed-point numbers, as they really designate a simple formula of the form _s*m n , however, they have a well defined interpretation and you can unfold them into something more suitable.

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.

In almost all modern systems, the specification for floating point arithmetic is the IEEE754 standard. This details everything from layout in memory to how truncation and rounding is propagated. It's a big area and someting you quite often need to take detailed account of in scientific and engineering programming.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM