The compiler is allowed to evaluate float expressions in any bigger precision it likes, so it looks like the first expression is evaluated in long double precision. In the second expression you enforce scaling the result down to float again.
In answer to some of your additional questions and the discussion below: you are basically looking for the smallest non-zero difference with 1 of some floating point type. Depending on the setting of FLT_EVAL_METHOD a compiler may decide to evaluate all floating point expressions in a higher precision than the types involved. On a Pentium traditionally the internal registers of the floating point unit are 80 bits and it is convenient to use that precision for all the smaller floating point types. So in the end your test depends on the precision of your compare !=. In the absence of an explicit cast the precision of this comparison is determined by your compiler not by your code. With the explicit cast you scale the comparison down to the type you desire.
As you confirmed your compiler has set FLT_EVAL_METHOD to 2 so it uses the highest precision for any floating point calculation.
As a conclusion to the discussion below we are confident to say that there is a bug relating to implementation of the FLT_EVAL_METHOD=2 case in gcc prior to version 4.5 and that is fixed from of at least version 4.6. If the integer constant 2 is used in the expression instead of the floating point constant 2.0, the cast to float is omitted in the generated assembly. It is also worth noticing that from of optimization level -O1 the right results are produced on these older compilers, but the generated assembly is quite different and contains only few floating point operations.
c - Floating point arithmetic and machine epsilon - Stack Overflow
c++ - Compare double to zero using epsilon - Stack Overflow
When double.Epsilon can equal 0
machine epsilon - C++ Forum
The compiler is allowed to evaluate float expressions in any bigger precision it likes, so it looks like the first expression is evaluated in long double precision. In the second expression you enforce scaling the result down to float again.
In answer to some of your additional questions and the discussion below: you are basically looking for the smallest non-zero difference with 1 of some floating point type. Depending on the setting of FLT_EVAL_METHOD a compiler may decide to evaluate all floating point expressions in a higher precision than the types involved. On a Pentium traditionally the internal registers of the floating point unit are 80 bits and it is convenient to use that precision for all the smaller floating point types. So in the end your test depends on the precision of your compare !=. In the absence of an explicit cast the precision of this comparison is determined by your compiler not by your code. With the explicit cast you scale the comparison down to the type you desire.
As you confirmed your compiler has set FLT_EVAL_METHOD to 2 so it uses the highest precision for any floating point calculation.
As a conclusion to the discussion below we are confident to say that there is a bug relating to implementation of the FLT_EVAL_METHOD=2 case in gcc prior to version 4.5 and that is fixed from of at least version 4.6. If the integer constant 2 is used in the expression instead of the floating point constant 2.0, the cast to float is omitted in the generated assembly. It is also worth noticing that from of optimization level -O1 the right results are produced on these older compilers, but the generated assembly is quite different and contains only few floating point operations.
The compiler is allowed to evaluate float expressions in any bigger precision it likes, so it looks like the first expression is evaluated in long double precision. In the second expression you enforce scaling the result down to float again.
In answer to some of your additional questions and the discussion below: you are basically looking for the smallest non-zero difference with 1 of some floating point type. Depending on the setting of FLT_EVAL_METHOD a compiler may decide to evaluate all floating point expressions in a higher precision than the types involved. On a Pentium traditionally the internal registers of the floating point unit are 80 bits and it is convenient to use that precision for all the smaller floating point types. So in the end your test depends on the precision of your compare !=. In the absence of an explicit cast the precision of this comparison is determined by your compiler not by your code. With the explicit cast you scale the comparison down to the type you desire.
As you confirmed your compiler has set FLT_EVAL_METHOD to 2 so it uses the highest precision for any floating point calculation.
As a conclusion to the discussion below we are confident to say that there is a bug relating to implementation of the FLT_EVAL_METHOD=2 case in gcc prior to version 4.5 and that is fixed from of at least version 4.6. If the integer constant 2 is used in the expression instead of the floating point constant 2.0, the cast to float is omitted in the generated assembly. It is also worth noticing that from of optimization level -O1 the right results are produced on these older compilers, but the generated assembly is quite different and contains only few floating point operations.
A C99 C compiler can evaluate floating-point expressions as if they were of a more precise floating-point type than their actual type.
The macro FLT_EVAL_METHOD is set by the compiler to indicate the strategy:
-1 indeterminable;
0 evaluate all operations and constants just to the range and precision of the type;
1 evaluate operations and constants of type float and double to the range and precision of the double type, evaluate long double operations and constants to the range and precision of the long double type;
2 evaluate all operations and constants to the range and precision of the long double type.
For historical reasons, two common choices when targeting the x86 processors are 0 and 2.
File m.c is your first program. If I compile it, using my compiler, thus, I obtain:
$ gcc -std=c99 -mfpmath=387 m.c
$ ./a.out
float eps = 1.084202e-19
./a.out
float eps = 1.192093e-07
If I compile this other program below, the compiler sets the macro according to what it does:
#include <stdio.h>
#include <float.h>
int main(){
printf("%d\n", FLT_EVAL_METHOD);
}
Results:
$ gcc -std=c99 -mfpmath=387 t.c
gcc -std=c99 t.c
$ ./a.out
0
Assuming 64-bit IEEE double, there is a 52-bit mantissa and 11-bit exponent. Let's break it to bits:
1.0000 00000000 00000000 00000000 00000000 00000000 00000000 ร 2^0 = 1
The smallest representable number greater than 1:
1.0000 00000000 00000000 00000000 00000000 00000000 00000001 ร 2^0 = 1 + 2^-52
Therefore:
epsilon = (1 + 2^-52) - 1 = 2^-52
Are there any numbers between 0 and epsilon? Plenty... E.g. the minimal positive representable (normal) number is:
1.0000 00000000 00000000 00000000 00000000 00000000 00000000 ร 2^-1022 = 2^-1022
In fact there are (1022 - 52 + 1)ร2^52 = 4372995238176751616 numbers between 0 and epsilon, which is 47% of all the positive representable numbers...
The test certainly is not the same as someValue == 0. The whole idea of floating-point numbers is that they store an exponent and a significand. They therefore represent a value with a certain number of binary significant figures of precision (53 in the case of an IEEE double). The representable values are much more densely packed near 0 than they are near 1.
To use a more familiar decimal system, suppose you store a decimal value "to 4 significant figures" with exponent. Then the next representable value greater than 1 is 1.001 * 10^0, and epsilon is 1.000 * 10^-3. But 1.000 * 10^-4 is also representable, assuming that the exponent can store -4. You can take my word for it that an IEEE double can store exponents less than the exponent of epsilon.
You can't tell from this code alone whether it makes sense or not to use epsilon specifically as the bound, you need to look at the context. It may be that epsilon is a reasonable estimate of the error in the calculation that produced someValue, and it may be that it isn't.
An epsilon is not relevant when you are checking which floating point value is bigger. It's only needed for equality, where (due to precision issues) your math may create two values which are supposed to be equal, but are slightly off.
It depends on your definition of "<=".
If you want to declare them equal if they are within a certain distance of each other, then you would do:
if ((a < (b+epsilon)) do_whatever();
This is counterintuitive, since it would accept a > b by less than epsilon, which is probably not what you want. But it might be.
In general, talking about floating-point (which includes doubles) equality is meaningless.
Is it OK to compare doubles in C? Like a == b. Will it give me correct results everytime? If not, workarounds?
What happens when doubles overflow? Does the C state machine go into an undefined state and then your program behavior is undefined/non deterministic? Or does something else happen? How does one prevent this from happening?
I thought the below is how I am suppose to compare float values. A) How am I suppose to compare doubles? B) What's the point of DBL_EPSILON?
#include <math.h>
#include <float.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int value = fabs((30.1L/5.0L) - 6.02L) <= DBL_EPSILON;
printf("Is same? %d\n", value);
return value;
}