When comparing doubles for equality, we need to give a tolerance level, because floating-point computation might introduce errors. For example:
double x;
double y;
x = f();
y = g();
if (fabs(x-y)<epsilon) {
// they are equal!
} else {
// they are not!
}
However, if I simply assign a constant value, without any computation, do I still need to check the epsilon?
double x = 1;
double y = 1;
if (x==y) {
// they are equal!
} else {
// no they are not!
}
Is ==
comparison good enough? Or I need to do fabs(x-y)<epsilon
again? Is it possible to introduce error in assigning? Am I too paranoid?
How about casting (double x = static_cast<double>(100)
)? Is that gonna introduce floating-point error as well?
I am using C++ on Linux, but if it differs by language, I would like to understand that as well.
If we do have to compare two floating-point numbers then rather than using “==” operator we will find the absolute difference between the numbers (which if were correctly represented, the difference would have been 0) and compare it with a very small number 1e-9 (i.e 10^-9, this number is very small) and if the ...
It is common knowledge that one has to be careful when comparing floating point values. Usually, instead of using == , we use some epsilon or ULP based equality testing.
Bitwise comparison. Direct ("exact") IEEE-754 comparison. Absolute margin comparison. Relative epsilon comparison.
Since the precision of float is less than the double therefore after a certain point(23 in float and 52 in double) it would truncate the result. Hence, after promotion of float into double(at the time of comparison) compiler will pad the remaining bits with zeroes.
Actually, it depends on the value and the implementation. The C++ standard (draft n3126) has this to say in 2.14.4 Floating literals
:
If the scaled value is in the range of representable values for its type, the result is the scaled value if representable, else the larger or smaller representable value nearest the scaled value, chosen in an implementation-defined manner.
In other words, if the value is exactly representable (and 1
is, in IEEE754, as is 100
in your static cast), you get the value. Otherwise (such as with 0.1
) you get an implementation-defined close match (a). Now I'd be very worried about an implementation that chose a different close match based on the same input token but it is possible.
(a) Actually, that paragraph can be read in two ways, either the implementation is free to choose either the closest higher or closest lower value regardless of which is actually the closest, or it must choose the closest to the desired value.
If the latter, it doesn't change this answer however since all you have to do is hardcode a floating point value exactly at the midpoint of two representable types and the implementation is once again free to choose either.
For example, it might alternate between the next higher and next lower for the same reason banker's rounding is applied - to reduce the cumulative errors.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With