This question already has an answer here:
-
using printf to print out floating values
3 answers
I have this code:
#include <stdio.h>
int main()
{
int i = 12345;
printf("%f", i);
return 0;
}
printf() will output 0.000000, shouldn't printf() interpret the bits contained in i
as a float number?
Technically this is undefined behaviour.
You should use a union to do this and print it with %e
instead of %f
, because it is a small number:
#include <stdio.h>
union int2float
{
int a;
float b;
};
int main()
{
union int2float tmp;
tmp.a = 12345;
printf("%e\n", tmp.b);
return 0;
}
This results in 1.729903e-41
.
with %.100f
you will get 0.0000000000000000000000000000000000000000172990295420898667405534417057140146406548336724655872023410
as output.
This is technically undefined behaviour, so anything can happen, for instance what @Art describes in his answer.
This answer here is therefore an explanation as to what would happen if you tried to print 12345 as a float assuming printf indeed sees the correct 32-bit value.
Let's analyze the binary representation for the number you are trying to represent.
Using http://www.h-schmidt.net/FloatConverter/IEEE754.html we can see that the decimal number 12345
has the following 32-bit representation:
decimal 12345
hexadecimal 0x00003039
Converted bit-to-bit to a IEEE-754 floating point 32-bit value, this represents:
float 1.7299E-41
let's try to print it:
#include <stdio.h>
int main() {
printf("%f\n", 1.7299E-41);
return 0;
}
This prints:
0.000000
Now let's read printf
man page, as found here: http://linux.die.net/man/3/printf
f, F
The double argument is rounded and converted to decimal notation in the style [-]ddd.ddd, where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6; if the precision is explicitly zero, no decimal-point character appears. If a decimal point appears, at least one digit appears before it.
The 1.7299E-41
value cannot be represented using this flag with the default precision, so the result you get is indeed the correct value.
The most likely reason printf
doesn't interpret the bits in i
as a floating point number is that printf
doesn't see i
at all. I suspect you're running x86_64 or a similar platform where the arguments are passed to functions in registers. Normally printf
would interpret your int as whatever format specifier you gave it. But floating point arguments to functions are handled differently on x86_64 and are put into different registers. So the reason you get 0 as output is that printf
pulls out the first floating point argument after the format string instead of the first general purpose register and prints that. Since you haven't used any floating point registers before your call to printf
they are most likely zeroed from program start.
Here's an experiment you can try:
#include <stdio.h>
int
main(int argc, char **argv)
{
printf("%f\n", 17.42);
printf("%f\n", 0x87654321);
return 0;
}
I get this output:
$ ./foo
17.420000
17.420000
Having said all that, the only correct answer is: this is undefined behavior, don't do this. But it's interesting to see what's going on under the hood.
If you want to dive into this and are running on Linux/MacOS/*BSD this document, section 3.2.3 describes how arguments are passed to functions (including varargs functions like printf). Windows does things slightly differently, but in this case the result on Windows would be exactly the same. printf
on Linux/MacOS/*BSD would expect the argument to be printed in %xmm0
(%xmm1
on Windows) while your call passes it in %rsi
(%rdx
on Windows).
Of course, if I'm wrong about x86_64, disregard everything I said and look at the answer from @SirDarius, because that applies to many (especially older) architectures. If you're on an alpha, sparc, powerpc, arm, etc. you're on your own. Call printf
once with an int, once with a float, disassemble the compiled code and see how arguments are passed.
If you want to print an int as float, cast it:
printf("%f", (float)i);
The only way printf()
knows the data-type of the arguments after the formatting string (and their count) is by reading the format string. The representation of an integer in memory is different from a floating point number. You pass printf() data in the format of an integer number but it assumes the format of a floating point number. This is why you get garbage in the console. You can correct this by type-casting.
printf("%f", (float) i);
when you use the %f
format specifier you have to use the float variable and print the value.
but you have declared i
as integer and trying to print using %f
it will print some value.
As it is a integer you have to use %d
specifier.
In printf %f
will search for the float variable. but there will be no float variable, so it prints some value.
You can type cast the integer value while printing.
printf("%f",(float)i);
To make i
as float
type you need to do type cast.
You can use
printf("%f", (float)i);
Example.
float myFloat;
int myInt;
myFloat = (float)myInt ; // Type casting
Try this
int i = 12345;
printf("%.2f", i/1.0f);