Is it safe to check floating point values for equality to 0?
I know you can't rely on equality between double or decimal type values normally, but I'm wondering if 0 is a special case.
While I can understand imprecisions between 0.00000000000001 and 0.00000000000002, 0 itself seems pretty hard to mess up since it's just nothing. If you're imprecise on nothing, it's not nothing anymore.
But I don't know much about this topic so it's not for me to say.
double x = 0.0;
return (x == 0.0) ? true : false;
Will that always return true?
Solution 1:
It is safe to expect that the comparison will return true
if and only if the double variable has a value of exactly 0.0
(which in your original code snippet is, of course, the case). This is consistent with the semantics of the ==
operator. a == b
means "a
is equal to b
".
It is not safe (because it is not correct) to expect that the result of some calculation will be zero in double (or more generally, floating point) arithmetics whenever the result of the same calculation in pure Mathematics is zero. This is because when calculations come into the ground, floating point precision error appears - a concept which does not exist in Real number arithmetics in Mathematics.
Solution 2:
If you need to do a lot of "equality" comparisons it might be a good idea to write a little helper function or extension method in .NET 3.5 for comparing:
public static bool AlmostEquals(this double double1, double double2, double precision)
{
return (Math.Abs(double1 - double2) <= precision);
}
This could be used the following way:
double d1 = 10.0 * .1;
bool equals = d1.AlmostEquals(0.0, 0.0000001);
Solution 3:
For your simple sample, that test is okay. But what about this:
bool b = ( 10.0 * .1 - 1.0 == 0.0 );
Remember that .1 is a repeating decimal in binary and can't be represented exactly, the same as trying to write 1/3 as a base 10 decimal. Now compare that to this code:
double d1 = 10.0 * .1; // make sure the compiler hasn't optimized the .1 issue away
bool b = ( d1 - 1.0 == 0.0 );
I'll leave you to run a test to see the actual results: you're more likely to remember it that way.