Inconsistent results while printing float as integer [duplicate] - c

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
print the float value in integer in C language
I am trying out a rather simple code like this:
float a = 1.5;
printf("%d",a);
It prints out 0. However, for other values, like 1.4,1.21, etc, it is printing out a garbage value. Not only for 1.5, for 1.25, 1.5, 1.75, 1.3125 (in other words, decimal numbers which can be perfectly converted into binary form), it is printing 0. What is the reason behind this? I found a similar post here, and the first answer looks like an awesome answer, but I couldn't discern it. Can any body explain why is this happening? What has endian-ness got to do with t?

you're not casting the float, printf is just interpreting it as an integer which is why you're getting seemingly garbage values.
Edit:
Check this example C code, which shows how a double is stored in memory:
int main()
{
double a = 1.5;
unsigned char *p = &a;
int i;
for (i=0; i<sizeof(double); i++) {
printf("%.2x", *(p+i));
}
printf("\n");
return 0;
}
If you run that with 1.5 it prints
000000000000f83f
If you try it with 1.41 it prints
b81e85eb51b8f63f
So when printf interprets 1.5 as an int, it prints zero because the 4 LSBs are zeros and some other value when trying with 1.41.
That being said, it is an undefined behaviour and you should avoid it plus you won't always get the same result it depends on the machine and how the arguments are passed.
Note: the bytes are reversed because this is compiled on a little indian machine which means the least significant byte comes first.

You don't take care about argument promotions. Because printf is a variadic function, the arguments are promoted:
C11 (n1570), § 6.5.2.2 Function calls
arguments that have type float are promoted to double.
So printf tries to interpret your double variable as an integer type. It leads to an undefined behavior. Just add a cast:
double a = 1.5;
printf("%d", (int)a);

Mismatch of arguments in printf is undefined beahivour
either typecast a or use %f
use this way
printf("%d",(int)a);
or
printf("%f",a);

d stands for : decimal. so, nevertheless a is float/double/integer/char,.... when you use : "%d", C will print that number by decimal. So, if a is integer type (integer, long), no problem. If a is char : because char is a type of integer, so, C will print value of char in ASCII.
But, the problem appears, when a is float type (float/double), just because if a is float type, C will have special way to read this, but not by decimal way. So, you will have strange result.
Why has this strange result ?
I just give a short explanation : in computer, real number is presented by two part: exponent and a mantissa. If you say : this is a real number, C will know which is exponent, which is mantissa. But, because you say : hey, this is integer. no difference between exponent part and mantissa part -> strange result.
If you want understand exactly, how can know which integer will it print (and of course, you can guess that). You can visit this link : represent FLOAT number in memory in C
If you don't want to have this trange result, you can cast int to float, so, it will print the integer part of float number.
float a = 1.5;
printf("%d",(int)a);
Hope this help :)

Related

The problem about printf function to "output float with %d" in C

I am a newbie to the C language. When I was learning floating point numbers today, I found the following problems.
float TEST= 3.0f;
printf("%x\n",TEST);
printf("%d\n",TEST);
first output:
9c9e82a0
-1667333472
second output:
61ea32a0
1642738336
As shown above, each execution will output different results. I have checked a lot of IEEE 754 format and still don't understand the reasons. I would like to ask if anyone can explain or provide keywords for me to study, thank you.
-----------------------------------Edit-----------------------------------
Thank you for your replies. I know how to print IEEE 754 bit pattern. However, as Nate Eldredge, chux-Reinstate Monica said, using %x and %d in printf is undefined behavior. If there is no floating point register in our device, how does it work ? Is this described in the C99 specification?
Most of the time, when you call a function with the "wrong kind" (wrong type) of argument, an automatic conversion happens. For example, if you write
#include <stdio.h>
#include <math.h>
printf("%f\n", sqrt(144));
this works just fine. The compiler knows (from the function prototype in <math.h>) that the sqrt function expects an argument of type double. You passed it the int value 144, so the compiler automatically converted that int to double before passing it to sqrt.
But this is not true for the printf function. printf accepts arguments of many different types, and as long as each argument is right for the particular % format specifier it goes with in the format string, it's fine. So if you write
double f = 3.14;
printf("%f\n", f);
it works. But if you write
printf("%d\n", f); /* WRONG */
it doesn't work. %d expects an int, but you passed a double. In this case (because printf is special), there's no good way for the compiler to insert an automatic conversion. So, instead, it just fails to work.
And when it "fails", it really fails. You don't even necessarily get anything "reasonable", like an integer representing the bit pattern of the IEEE-754 floating-point number you thought you passed. If you want to inspect the bit pattern of a float or double, you'll have to do that another way.
If what you really wanted to do was to see the bits and bytes making up a float, here's a completely different way:
float test = 3.14;
unsigned char *p = (unsigned char *)&test;
int i;
printf("bytes in %f:", test);
for(i = 0; i < sizeof(test); i++) printf(" %02x", p[i]);
printf("\n");
There are some issues here with byte ordering ("endianness"), but this should get you started.
To print hex (ie how it is represented in the memory) representation of the float:
float TEST= 3.0f;
int y=0;
memcpy(&y, &TEST, sizeof(y));
printf("%x\n",y);
printf("%d\n",y);
or
union
{
float TEST;
int y;
}uf = {.y = 0};
uf.TEST = 3.0f;
printf("\n%x\n",(unsigned)uf.y);
printf("%d\n",uf.y);
Both examples assuming sizeof(float) <= sizeof(int) (if they are not equal I need to zero the integer)
And the result (same for both):
40400000
1077936128
As you can see it is completely different from your one.
https://godbolt.org/z/Kr61x6Kv3

type of numbers that are not stored in a variable [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 4 years ago.
I'm a Little confused about some numbers in C-Code. I have the following piece of Code
int k;
float a = 0.04f;
for (k=0; k*a < 0.12; k++) {
* do something *
}
in this case, what is the type of "0.12" ? double ? float ? it has never been declared anywhere. Anyways, in my program the Loop above is excuted 4 times, even though 3*0.04=0.12 < 0.12 is not true. Once I Exchange 0.12 with 0.12F (because I am globally restricted to float precision in all of the program), the Loop is now executed 3 times. I do not understand why, and what is happening here. Are there any proper Guidelines on how to write such statements to not get unexpected issues?
Another related issue is the following: in the Definition of variables, say
float b = 1/180 * 3.14159265359;
what exactly "is" "1" in this case ? and "180" ? Integers ? Are they converted to float numbers ? Is it okay to write it like that ? Or should it be "1.0f/180.0f*3.14159265359f;"
Last part of the question,
if i have a fuction
void testfunction(float a)
which does some things.
if I call the fuction with testfunction(40.0/6.0), how is that Division handled ? It seems that its calculated with double precision and then converted to a float. Why ?
That was a Long question, I hope someone can help me understand it.
...numbers that are not stored in a variable
They are called "constants".
Any unsuffixed floating point constant has type double.
Quoting C11, chapter §6.4.4.2
An unsuffixed floating constant has type double. If suffixed by the letter f or F, it has
type float. If suffixed by the letter l or L, it has type long double.
For Integer constants, the type will depend on the value.
Quoting C11, chapter §6.4.4.1,
The type of an integer constant is the first of the corresponding list in which its value can
be represented. [..]
and for unsuffixed decimal number, the list is
int
long int
long long int
Regarding the mathematical operation accuracy of floating point numbers, see this post
"0.12" is a constant, and yes, without a trailing f or F, it will be interpreted as a double.
That number can not be expressed exactly as a binary fraction. When you compare k * a, the result is a float because both operands are floats. The result is slightly less than 0.12, but when you compare against a double, it gets padded out with zeros to the required size, which increases the discrepancy. When you use a float constant, the result is not padded (cast), and by good luck, comes out exactly equal to the binary representation of "0.12f". This would likely not be the case for a more complicated operation.
if we use a fractional number for eg, like 3.4 it's default type if double. You should explicitly specify it like 3.4f if you want it to consider as single precision (float).
if you call the following function
int fun()
{
float a= 1.2f;
double b = 1.2;
return (a==b);
}
this will always return zero (false).because before making comparison the float type is converted to double (lower type to higher type) , At this time sometimes it can't reproduce exact 1.2, a slight variations in value can be happen after 6th position from decimal point. You can check the difference by the following print statement
printf("double: %0.9f \n float: %0.9f\n",1.2,1.2f);
It results ike
double: 1.200000000
float: 1.200000481

Adding an Integer to a float not working as expected

I know the following will not print 2.9 or 3. I can correct it but really want to understand what is internally happening so it is printing:
858993459
How does this number come ?
I am running this under windows 32 bit
int main()
{
double f = 1.9;
int t = 1;
printf("%d\n", t+f);
return 0;
}
Update
Simply believing that this would be "undefined behavior" was not possible for me, so I thought of investigating it further. I found this answer exactly what I wanted to understand.
As others have already mentioned, this is undefined behaviour. But by taking some assumptions about the machine architecture, one can answer why it is printing these numbers:
Using IEEE 754 64-bit format to represent doubles values, the value of 2.9 is the a stored as 0x4007333333333333.
In a Little-Endian machine, the %d specifier will read the lower 4 bytes of that value, which are 0x33333333, which equals 858.993.459
you're using wrong format specifier. use %f instead.
As per the implicit type promotion rule, while doing t+f, t will be promoted to double. You're trying to print a double value using %d, which is supposed to expect an int.
Note: While using wrong format specifier, the behaviour is undefined.
Related reading: c99 standard, chapter 7.19.6.1, paragraph 9, (emphasis mine)
If a conversion specification is invalid, the behavior is undefined. If any argument is
not the correct type for the corresponding conversion specification, the behavior is
undefined.
What happened is you try print a double using %d, so printf interpret this how an integer, but for you understand why this printed value, you have to understand how a double is stored by C language, C uses the IEEE 754 standard:
So %d interpret this as integer, and when you add an int and an double C keep this as double to not lose any part, and the result is a double, and %d interpret this sum as a integer, and like the format is different you see garbage.
you should use %f instead.
You are trying to add integer and double so according to the thumb rule(type promotion rule) i.e. while this addition happens the integer will be promoted to double and the summation will happen and you are trying to print double value using %d format specifier which will lead to undefined behavior.
Use %f instead
PS: Using a wrong format specifer to print the value will lead to undefined behavior that is what you are seeing here.
%d will transfer double to int
double f = 1.9;
printf("%d\n", f);
Outputs:
1717986918
Computers store ints and doubles in different ways, you can see it here:
http://en.wikipedia.org/wiki/Double-precision_floating-point_format

float variables in C [duplicate]

This question already has answers here:
Using %f to print an integer variable
(6 answers)
Closed 3 years ago.
May be this is a simple question but I am not sure about how float variables are stored in memory and why it is behaving in this way, can someone please explain about the following behavior.
#include<stdio.h>
int main ()
{
int a = 9/5;
printf("%f\n", a);
return 0;
}
Output:
0.000000
I have looked at some information on how float variables are stored in memory, it has stuff about mantissa, exponent and sign. But I am not getting how to relate that here.
int a = 9/5;
performs integer division and ignores the remainder, so a is set to 1. Attempting to print that using %f gives undefined behavior, but by chance you got 0.000000 out of it.
Do
double a = 9./5.;
instead, or print with %d if integer division was the desired behavior. (float would also work, but a will be promoted to double when passed to printf, so there's no reason not to use double.)
It is an Undefined Behaviour.
You are using float format specifier (%f) to print an int (a). You should use %d to see correct output.
It is an undefined behaviour in C. Use %d format specifier instead of %f.
Does printf() depend on order of format specifiers? gives you detailed answer.
Here's a brief analysis of your code:
int a = 9/5; // 9/5 = 1.8, but since you are doing integer division and storing the value in an integer it will store 1.
printf("%f\n", a);//Using incorrect format specifiers with respect to datatypes, will cause undefined behavior
printf("%d\n",a);//This should print 1. And correct.
Or if you want the float:
instead of int use float :
float a=9.0f/5;//This will store 1.800000f
//float a=9/5 will store 1.000000 not, 1.8 because of integer divison
printf("%f\n",a); //This will print 1.800000
Also do read this: http://en.wikipedia.org/wiki/IEEE_754-2008 on how floating points work.
Clarification about integer division:
C99:
6.5.5 Multiplicative operators
6 When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded.88) If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a
88) This is often called ‘‘truncation toward zero’’.
Just assuming that your division should result in a fraction in normal math won't magically make it a float.
int a = 9/5;
You need to use
float a = 9.0/5;
First you need the right data type i.e. float (or better yet double for higher precision) to store a float.
Secondly, if you are dividing two integers i.e. 9 and 5, it will simply follow integer division i.e. only store the integer part of division and discard the rest. To avoid that i have added .0 after 9. This would force compiler to implicitly covert into float and do the division.
Regarding your mentioning of why it is printing 0, it is already mentioned that trying %f on integer is undefined behavior. Technically, a float is 4 bytes containing 3 byte number and 1 byte exponent and these are combined to generate the resultant value.

Handling numbers in C

Couldnt understand how numbers are handled in C. Could anyone point to a good tutorial.
#include<stdio.h>
main()
{
printf("%f",16.0/3.0);
}
This code gave: 5.333333
But
#include<stdio.h>
main()
{
printf("%d",16.0/3.0);
}
Gave some garbage value: 1431655765
Then
#include<stdio.h>
main()
{
int num;
num=16.0/3.0;
printf("%d",num);
}
Gives: 5
Then
#include<stdio.h>
main()
{
float num;
num=16/3;
printf("%f",num);
}
Gives: 5.000000
printf is declared as
int printf(const char *format, ...);
the first arg (format) is string, and the rest can be anything. How the rest of the arguments will be used depending on the format specifiers in format. If you have:
printf("%d%c", x, y);
x will be treated as int, y will be treated as char.
So,
printf("%f",16.0/3.0);
is ok, since you ask for float double (%f), pass float double(16.0/3.0)
printf("%d",16.0/3.0);
you ask for int(%d), you pass float double (double and int have different internal representation) so, the bit representation of 16.0/3.0 (double) corresponds to bit representation of 1431655765(int).
int num;
num=16.0/3.0;
compiler knows that you are assigning to int, and converts it for you. Note that this is different than the previous case.
Ok, the first 1 is giving correct value as expected.
Second one you are passing a float while it is treating it as an int (hence the "%d" which is for displaying int datatypes, it is a little complicated to explain why and since it appears your just starting I wouldn't worry about why "%d" does this when passed a float) reading it wrong therefore giving you a wierd value. (not a garbage value though).
Third one it makes 16.0/3.0 an int while assigning it to the int datatype which will result in 5. Because while making the float an int it strips the decimals regardless of rounding.
In the fourth the right hand side (16/3) is treated as an int because you don't have the .0 zero at the end. It evaluates that then assigns 5 to float num. Thus explaining the output.
It is because the formatting strings you are choosing do not match the arguments you are passing. I suggest looking at the documentation on printf. If you have "%d" it expects an integer value, how that value is stored is irrelevant and likely machine dependent. If you have a "%f" it expects a floating point number, also likely machine dependent. If you do:
printf( "%f", <<integer>> );
the printf procedure will look for a floating point number where you have given an integer but it doesn't know its and integer it just looks for the appropriate number of bytes and assumes that you have put the correct things there.
16.0/3.0 is a float
int num = 16.0/3.0 is a float converted to an int
16/3 is an int
float num = 16/3 is an int converted to a float
You can search the web for printf documentation. One page is at http://linux.die.net/man/3/printf
You can understand numbers in C by using concept of Implecit Type Conversion.
During Evaluation of any Expression it adheres to very strict rules of type Conversion.
and your answer of expression is depends on this type conversion rules.
If the oparands are of different types ,the 'lower' type is automatically converted into the 'higher' type before the operation proceeds.
the result is of the higher type.
1:
All short and char are automatically converted to int then
2:
if one of the operands is int and the other is float, the int is converted into float because float is higher than an ** int**.
if you want more information about inplicit conversion you have to refer the book Programming in ANSI C by E Balagurusamy.
Thanks.
Bye:DeeP
printf formats a bit of memory into a human readable string. If you specify that the bit of memory should be considered a floating point number, you'll get the correct representation of a floating point number; however, if you specify that the bit of memory should be considered an integer and it is a floating point number, you'll get garbage.
printf("%d",16.0/3.0);
The result of 16.0/3.0 is 5.333333 which is represented in Single precision floating-point format as follows
0 | 10101010 | 10101010101010101010101
If you read it as 32bit integer value, the result would be 1431655765.
num=16.0/3.0;
is equivalent to num = (int)(16.0/3.0). This converts the result of float value(5.33333) to integer(5).
printf("%f",num);
is same as printf("%f",(float)num);

Resources