Float and double output [duplicate] - c

This question already has answers here:
strange output in comparison of float with float literal
(8 answers)
Closed 9 years ago.
Please explain the output for different cases
#include<stdio.h>
int main()
{
float a=5.9; //a=0.9
if (a==5.9)
printf("Equal");
else if (a<5.9)
printf("Less than");
else
printf("Greater than");
return 0;
}
When a is 5.9 the output is "Greater than", when a is 0.9 the output is "Less than". Why?

In C, the literal “5.9” has type double and is converted by common compilers to 5.9000000000000003552713678800500929355621337890625, because they use binary IEEE-754 floating point, and that number is the value representable as a double that is closest to 5.9. Your code initializes a float with that value. That requires converting a double to a float, and the result is 5.900000095367431640625, because that is the float value that is closest to the double value. Obviously, the latter is greater than the former, which is why your output is “Greater than”.
With .9, the literal “.9” is converted to the double 0.90000000000000002220446049250313080847263336181640625. Then that double is converted to the float 0.89999997615814208984375, which is obviously less than the double.

Your variable is a float but the constant is a double. Since that value can't be stored precisely ti will be stored differently as a float and as a double. If you use the same data types you'll get the desired results
http://codepad.org/1q5mwFGd
http://codepad.org/Q4lOQnG8

Floating point numbers are inherently imprecise. For a quick introduction, you can read up a bit here. http://floating-point-gui.de/errors/comparison/
For some suggestions on effective comparison strategies, see this post. What is the most effective way for float and double comparison?

This is because internally, the floating point numbers are stored in binary form and 5.9 can't be represented exactly as 5.9. Have a look at the following similar question and answer: Why does a C floating-point type modify the actual input of 125.1 to 125.099998 on output?

When comparing floating-point numbers it is best to avoid '=='.
This because some values cannot be correctly stored without some loss of precision.
So it is better to say:
if( fabs(a-5.9) < .0001 ) {
// 'EQUAL' or at least near enough!
}
I know this takes more to compute, but it will behave the way you expect.

Due to decimal binary conversion, 0.9 represented as a summation of powers of 2^-1:
0.9 - (0.5 + 0.25 + 0.125) = 0.025
But 0.025 is not an exact power of 2^-1. So you need to represent both numbers in the comparison with the same precision. Since float and double have different precision they compare not equal.

Related

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

printf behaviour in C

I am trying to understand what is the difference between the following:
printf("%f",4.567f);
printf("%f",4.567);
How does using the f suffix change/influence the output?
How using the 'f' changes/influences the output?
The f at the end of a floating point constant determines the type and can affect the value.
4.567 is floating point constant of type and precision of double. A double can represent exactly typical about 264 different values. 4.567 is not one on them*1. The closest alternative typically is exactly
4.56700000000000017053025658242404460906982421875 // best
4.56699999999999928235183688229881227016448974609375 // next best double
4.567f is floating point constant of type and precision of float. A float can represent exactly typical about 232 different values. 4.567 is not one on them. The closest alternative typically is exactly
4.566999912261962890625 // best
4.56700038909912109375 // next best float
When passed to printf() as part of the ... augments, a float is converted to double with the same value.
So the question becomes what is the expected difference in printing?
printf("%f",4.56700000000000017053025658242404460906982421875);
printf("%f",4.566999912261962890625);
Since the default number of digits after the decimal point to print for "%f" is 6, the output for both rounds to:
4.567000
To see a difference, print with more precision or try 4.567e10, 4.567e10f.
45670000000.000000 // double
45669998592.000000 // float
Your output may slightly differ to to quality of implementation issues.
*1 C supports many floating point encodings. A common one is binary64. Thus typical floating-point values are encoded as an sign * binary fraction * 2exponent. Even simple decimal values like 0.1 can not be represented exactly as such.

Why does float give different outputs if we use it with if and 'equal to' operator? Please see the code below: [duplicate]

This question already has answers here:
strange output in comparison of float with float literal
(8 answers)
Closed 6 years ago.
float f=2.2;
if (f==2.2)
printf("abc");
else
printf("xyz");
This code prints xyz,while if we give 2.5 instead of 2.2 the output is abc.
2.2 is a double that is not exactly representable in binary floating point. In effect, you are comparing the double 2.2 to the result of converting it to float, with rounding, and then back to double.
Assuming double is IEEE 754 64-bit binary floating point, and float is IEEE 754 32-bit binary floating point, the closest double to decimal 2.2 has exact value 2.20000000000000017763568394002504646778106689453125, and the result of converting it to float is 2.2000000476837158203125. Converting the float back to double does not change its value. 2.20000000000000017763568394002504646778106689453125 is not equal to 2.2000000476837158203125.
2.5 is exactly representable in both float and double in binary floating point systems, so neither the conversion to float nor the conversion back to double changes the value. 2.5 is equal to 2.5.
Floating-point numbers are likely to contain round-off error
Ref: http://www.cs.yale.edu/homes/aspnes/pinewiki/C(2f)FloatingPoint.html
Going through the documentation,
I see the following. (Point 6 in the URL above)
In general, floating-point numbers are not exact: they are likely to contain round-off error because of the truncation of the mantissa to a fixed number of bits.
The easiest way to avoid accumulating error is to use high-precision floating-point numbers (this means using double instead of float). On modern CPUs there is little or no time penalty for doing so....
One consequence of round-off error is that it is very difficult to test floating-point numbers for equality, unless you are sure you have an exact value as described above. It is generally not the case, for example, that (0.1+0.1+0.1) == 0.3 in C. This can produce odd results if you try writing something like for(f = 0.0; f <= 0.3; f += 0.1): it will be hard to predict in advance whether the loop body will be executed with f = 0.3 or not. (Even more hilarity ensues if you write for(f = 0.0; f != 0.3; f += 0.1), which after not quite hitting 0.3 exactly keeps looping for much longer than I am willing to wait to see it stop, but which I suspect will eventually converge to some constant value of f large enough that adding 0.1 to it has no effect.)

Float point numbers are not equal, despite being the same? [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Identical float values comparing as inequal [duplicate]
(4 answers)
Closed 3 years ago.
The program below outputs This No. is not same. Why does it do this when both numbers are the same?
void main() {
float f = 2.7;
if(f == 2.7) {
printf("This No. is same");
} else {
printf("This No. is not same");
}
}
Why does it do this when both numbers are the same?
The numbers are not the same value.
double can represent exactly typically about 264 different values.
float can represent exactly typically about 232 different values.
2.7 is not one of the values - some approximations are made given the binary nature of floating-point encoding versus the decimal text 2.7
The compiler converts 2.7 to the nearest representable double or
2.70000000000000017763568394002504646778106689453125
given the typical binary64 representation of double.
The next best double is
2.699999999999999733546474089962430298328399658203125.
Knowing the exact value beyond 17 significant digits has reduced usefulness.
When the value is assigned to a float, it becomes the nearest representable float or
2.7000000476837158203125.
2.70000000000000017763568394002504646778106689453125 does not equal 2.7000000476837158203125.
Should a compiler use a float/double which represents 2.7 exactly like with decimal32/decimal64, code would work as OP expected. double representation using an underlying decimal format is rare. Far more often the underlying double representation is base 2 and these conversion artifacts need to be considered when programming.
Had the code been float f = 2.5;, the float and double value, using a binary or decimal underlying format, would have made if (f == 2.5) true. The same value as a high precision double is representable exactly as a low precision float.
(Assuming binary32/binary64 floating point)
double has 53 bits of significance and float has 24. The key is that if the number as a double has its least significant (53-24) bits set to 0, when converted to float, it will have the same numeric value as a float or double. Numbers like 1, 2.5 and 2.7000000476837158203125 fulfill that. (range, sub-normal, and NaN issues ignored here.)
This is a reason why exact floating point comparisons are typically only done in select situations.
Check this program:
#include<stdio.h>
int main()
{
float x = 0.1;
printf("%zu %zu %zu\n", sizeof(x), sizeof(0.1), sizeof(0.1f));
return 0;
}
Output is 4 8 4.
The values used in an expression are considered as double (double precision floating point format) unless a f is specified at the end. So the expression “x==0.1″ has a double on right side and float which are stored in a single precision floating point format on left side.
In such situations float is promoted to double .
The double precision format uses uses more bits for precision than single precision format.
In your case add 2.7f to get expected result.
The literal 2.7 in f == 2.7 is converted to double that's why 2.7 is not equal to f.

C : Strange error when using float and double [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
strange output in comparision of float with float literal
Comparison of float and double variables
I have a test with double and float in C, but I cannot explain why.
float x = 3.4F;
if(x==3.4)
printf("true\n");
else printf("false\n");
double y = 3.4;
if (y==3.4)
printf("true\n");
else printf("false\n");
The result will be False and True. Please explain for me please.
3.4 cannot be exactly represented as a double for the same reason that one third cannot be exactly represented as a base-10 decimal number using a finite number of digits -- the representation recurs.
So, the double literal 3.4 is actually the double value closest to 3.4. 3.4F is the float value closest to 3.4, but that's different from the closest double value.
When you compare a float with a double, the float is converted to double, which doesn't change its value.
Hence, 3.4F != 3.4, just as 0.3333 != 0.33333333
x == 3.4 should be x == 3.4F, otherwise the 3.4 is a double (by default). Always compare like with like, not apples and oranges.
Edit:
Whether the result of the comparison between types of different precision is true or false depends on the floating point representation of the compiler.
Floating point numbers, whether single precision (float) or double, are an approximation.
No guarantee that the result will be false and true, but the basic idea is pretty simple: 3.4 has type double. When you assign it to a float, it'll get rounded. When you compare, that rounded number will be promoted back to a double, not necessarily the same double as 3.4.
In the second case, everything's double throughout.
Comparing for equality
Floating point math is not exact. Simple values like 0.2 cannot be precisely represented using binary floating point numbers, and the limited precision of floating point numbers means that slight changes in the order of operations can change the result. Different compilers and CPU architectures store temporary results at different precisions, so results will differ depending on the details of your environment. If you do a calculation and then compare the results against some expected value it is highly unlikely that you will get exactly the result you intended.
In other words, if you do a calculation and then do this comparison:
if (result == expectedResult)
then it is unlikely that the comparison will be true. If the comparison is true then it is probably unstable – tiny changes in the input values, compiler, or CPU may change the result and make the comparison be false.
As a tip, comparing floating point numbers (float or double) with '==' is in most cases a bad programming practice, as you might never get the statement to be true. The two numbers might differ in their least significant bits.
It is better using something like:
abs(x - y) < EQUALITY_MARGIN
With EQUALITY_MARGIN being an adequately small number.

Resources