Amit Yadav
Amit Yadav

Reputation: 1861

Float comparison gives different results

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

Answers (7)

wormsparty
wormsparty

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

undur_gongor
undur_gongor

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

Shahbaz
Shahbaz

Reputation: 47493

First of all, as others mentioned, use values like 0.8f when working with floats.

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

John Beckett
John Beckett

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

Mr_Spock
Mr_Spock

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

embeddedlinux1987
embeddedlinux1987

Reputation: 71

Try this:

Instead of "if(a<0.9)" compare using "if(a<0.9f)"

Upvotes: -1

Constantinius
Constantinius

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

Related Questions