Comparing Same Float Values In C

24,615

Solution 1

While many people will tell you to always compare floating point numbers with an epsilon (and it's usually a good idea, though it should be a percentage of the values being compared rather than a fixed value), that's not actually necessary here since you're using constants.

Your specific problem here is that:

float a = 0.7;

uses the double constant 0.7 to create a single precision number (losing some precision) while:

if (a == 0.7)

will compare two double precision numbers (a is promoted first).

The precision that was lost when turning the double 0.7 into the float a is not regained when promoting a back to a double.

If you change all those 0.7 values to 0.7f (to force float rather than double), or if you just make a a double, it will work fine - I rarely use float nowadays unless I have a massive array of them and need to save space.

You can see this in action with:

#include <stdio.h>
int main (void){
    float f = 0.7;    // double converted to float
    double d1 = 0.7;  // double kept as double
    double d2 = f;    // float converted back to double

    printf ("double:            %.30f\n", d1);
    printf ("double from float: %.30f\n", d2);

    return 0;
}

which will output something like (slightly modified to show difference):

double:            0.6999999|99999999955591079014994
double from float: 0.6999999|88079071044921875000000
                            \_ different beyond here.

Solution 2

Floating point number are not what you think they are: here are two sources with more information: What Every Computer Scientist Should Know About Floating-Point Arithmetic and The Floating-Point Guide.

The short answer is that due to the way floating point numbers are represented, you cannot do basic comparison or arithmetic and expect it to work.

Solution 3

You are comparing a single-precision approximation of 0.7 with a double-precision approximation. To get the expected output you should use:

if(a == 0.7f) // check a is exactly 0.7f

Note that due to representation and rounding errors it may be very unlikely to ever get exactly 0.7f from any operation. In general you should check if fabs(a-0.7) is sufficiently close to 0.

Don't forget that the exact value of 0.7f is not really 0.7, but slightly lower:

0.7f = 0.699999988079071044921875

The exact value of the double precision representation of 0.7 is a better approximation, but still not exactly 0.7:

0.7d = 0.6999999999999999555910790149937383830547332763671875

Solution 4

a is a float; 0.7 is a value of type double.

The comparison between the two requires a conversion. The compiler will convert the float value to a double value ... and the value resulting from converting a float to a double is not the same as the value resulting from the compiler converting a string of text (the source code) to a double.

But don't ever compare floating point values (float, double, or long double) with ==.

You might like to read "What Every Programmer Should Know About Floating-Point Arithmetic".

Share:
24,615
gursahib.singh.sahni
Author by

gursahib.singh.sahni

Updated on December 08, 2020

Comments

  • gursahib.singh.sahni
    gursahib.singh.sahni over 3 years

    Possible Duplicate:
    strange output in comparison of float with float literal

    When I am trying to compare 2 same float values it doesn't print "equal values" in the following code :

    void main()
    {
        float a = 0.7;
        clrscr();
        if (a < 0.7)
            printf("value :  %f",a);
        else if (a == 0.7)
            printf("equal values");
        else
            printf("hello");
        getch();
    }
    

    Thanks in advance.

  • Mike Kwan
    Mike Kwan about 12 years
    You need to get the absolute value of the result of the subtraction result or the epsilon only grows one way.
  • Mike Kwan
    Mike Kwan about 12 years
    Can be simplified to: return fabs(f1 - f2) < 0.00001
  • Pascal Cuoq
    Pascal Cuoq about 12 years
    Thanks for writing an answer that does not suggest an epsilon. This blog post I wrote some time ago has more examples of behaviors that may be surprising. blog.frama-c.com/index.php?post/2011/11/08/Floating-point-qu‌​iz
  • Olof Forshell
    Olof Forshell about 12 years
    The epsilon method appears straightforward but is actually quite complex in that the epsilon chosen should be a function of the exponent of the value being compared (a vector of constants, one for each possible exponent is one solution). In addition as you approach the extreme values of the exponent epsilon becomes less and less useful as its value approaches that of the value being compared with.
  • Olof Forshell
    Olof Forshell about 12 years
    Uh ... what if f1 and f2 are smaller than 0.00001?
  • Olof Forshell
    Olof Forshell about 12 years
    There is no such thing as "lack of absolute precision in floats." Their precision is absolute and the values are exact. The problem is that they are based on base 2 arithmetic and we normally use base 10. Base 10 values may or may not have an exact equivalent in base 2 and vice versa. 0.5 and 10.125 are examples of exact equivalents. 0.3 and 11.6 examples of when there is no equivalent.
  • enthusiasticgeek
    enthusiasticgeek over 9 years
    @OlofForshell How about he can modify the statement as float precision = 0.00001*f1*f2;?
  • SpawN
    SpawN over 2 years
    why does it not work with 0.5f ? 0.5 = .1 ; thats it and its mantissa also fits in the single precision floating format.