Reputation: 1861
Look at the following two codes, and tell me the reason why answers vary a lot.
#include<stdio.h>
int main() {
float a = 0.9;
if(a<0.9)
printf("hi"); // This will be the answer
else
printf("bye");
return 0;
}
And if we change 0.9 to 0.8, then else's statement is printed:
#include<stdio.h>
int main() {
float a = 0.8;
if(a<0.8)
printf("hi");
else
printf("bye");//this will be the answer
return 0;
}
So why this output changes when we just change a single digit?
Upvotes: 3
Views: 2153
Reputation: 2499
You have to know how floating points works.
Floating points are represented by using powers of two, each digit is used to represent 2^-x
where X is the n-th digit.
For example, 0.011
(binary) would be 2^-2 + 2^-3
, which is 0.25 + 0.125 = 0.375
Now try to represent 0.9
. You are in trouble, since no power of two to represent it. The value this is represented in 32-bits and probably 64-bits machines will give a result slightly smaller than 0.9, whereas for 0.8 the result is precise and representable by powers of two.
You can try this out by opening a python
prompt. Try and type a few numbers, eventually one will end with ...99999999
.
Upvotes: 1
Reputation: 15954
The literals 0.9
and 0.8
have type double
. Since both values cannot be represented exactly, they will in fact be 0.9000000000000000222...
and 0.8000000000000000444...
.
When stored in the float
(single precision) variable a
they will be converted to single and become even more inaccurate: 0.89999997...
and 0.8000000119...
.
For the comparison with the literal double
value they are converted back to double
retaining the more inaccurate value.
As you can see from the numbers above, the comparison yields different results for 0.9
and 0.8
.
All this is assuming your platform has IEEE754 floats which is most probably the case.
You can see single/double representations of numbers at www.binaryconvert.com.
Upvotes: 5
Reputation: 47493
First of all, as others mentioned, use values like 0.8f
when working with float
s.
Also, floating point ==
comparison is something you would want to avoid because of the precision of this operation in the FPU. What always worked best for me, was to define a margin, let's say 1e-6f
(or the precision you need based on your application) and instead of this:
if (LHS == RHS)
you write:
if (LHS-RHS < MARGIN && RHS-LHS < MARGIN)
You could write a function (if you are a c++ fan) or macro (if you are a c fan (here comes the -1s)) that does this for you.
Upvotes: 0
Reputation: 126
This is due to rounding errors, to see the value of that you are using insert a printf before the if:
printf("a=%f\n", a);
Upvotes: 0
Reputation: 3835
According to the C Standard:
6.3.1.5 Real floating types
1) When a float is promoted to double or long double, or a double is promoted to long double, its value is unchanged.
2) When a double is demoted to float, a long double is demoted to double or float, or a value being represented in greater precision and range than required by its semantic type (see 6.3.1.8) is explicitly converted to its semantic type, if the value being converted can be represented exactly in the new type, it is unchanged. If the value being converted is in the range of values that can be represented but cannot be represented exactly, the result is either the nearest higher or nearest lower representable value, chosen in an implementation-defined manner. If the value being converted is outside the range of values that can be represented, the behavior is undefined.
The standard can be found here.
Upvotes: 1
Reputation: 71
Try this:
Instead of "if(a<0.9)" compare using "if(a<0.9f)"
Upvotes: -1
Reputation: 35039
This error is due to floating point accuracy and because you are comparing a float
type with a double
value. Try to compare it versus floating point literals: if(a<0.8f)
I suggest you read the according wikipedia article, it explains in detail why your error happens.
Upvotes: 10