Comparing Same Float Values In C
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".
gursahib.singh.sahni
Updated on December 08, 2020Comments
-
gursahib.singh.sahni over 3 years
Possible Duplicate:
strange output in comparison of float with float literalWhen 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 about 12 yearsYou need to get the absolute value of the result of the subtraction result or the epsilon only grows one way.
-
Mike Kwan about 12 yearsCan be simplified to:
return fabs(f1 - f2) < 0.00001
-
Pascal Cuoq about 12 yearsThanks 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-quiz
-
Olof Forshell about 12 yearsThe 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 about 12 yearsUh ... what if f1 and f2 are smaller than 0.00001?
-
Olof Forshell about 12 yearsThere 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 over 9 years@OlofForshell How about he can modify the statement as
float precision = 0.00001*f1*f2;
? -
SpawN over 2 yearswhy does it not work with 0.5f ? 0.5 = .1 ; thats it and its mantissa also fits in the single precision floating format.