Convert int to float: how it is done
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 afloat
(23 for a 32 bit single-precision float). If there are any remaining bits in theint
(that is, if it's greater than 224), and the next bit after the ones you have room for is1
, you may or may not round up depending on the IEEE rounding mode in operation. - copy the sign bit from the
int
to thefloat
.
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.
Comments
-
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 almost 12 yearsThat is fine for the mantissa, you need to add that the exponent needs to be computed
-
Sebastian Mach almost 12 yearshow about explaining it a little bit? mention what this code does and I guarantee at least one upvote :)
-
Sebastian Mach almost 12 yearsit pragmatically answers the question
what magic the complier actually does
with a good link, +1. -
Joseph Willcoxson almost 12 yearsFirst 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 almost 12 years+1 for the comment, but how about adding this information to your answer?