Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Floating-point comparison of constant assignment

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.

like image 734
CuriousMind Avatar asked Mar 23 '12 04:03

CuriousMind


People also ask

How do you find the floating point comparison?

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 ...

Which of the following is used to check the floating point equality?

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.

What are the two approaches used for comparing floating point numbers?

Bitwise comparison. Direct ("exact") IEEE-754 comparison. Absolute margin comparison. Relative epsilon comparison.

Can float and double be compared in C?

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.


1 Answers

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.

like image 72
paxdiablo Avatar answered Oct 24 '22 03:10

paxdiablo