Well, yes and no. If all of the floating-point values you are comparing are stored as constants and the constants are the same data width (i.e., you compare float
to float
and double
to double
), this is a safe operation. But if everything you were comparing was a constant, why not use integers or enums?
In general, comparing floating-point numbers for equality is unsafe. The reason for this is that floating-point numbers can't perfectly store all values. This is a lot like the problem with the number 1/3 in decimal which we would have to write as 0.33333... The same problem exists for storing fractional parts in binary, and numbers that have finite representations in decimal notation are not guaranteed to have finite binary representations. Since we are limited to 32 or 64 bits, part of the number gets truncated. This means that performing math operations on floating-point numbers could result in unexpected consequences.
Consider this quote from this post from Bruce M. Bush:
At the heart of many strange results is one fundamental: floating-point on computers is usually base 2, whereas the external representation is base 10. We expect that 1/3 will not be exactly representable, but it seems intuitive that .01 would be. Not so! .01 in IEEE single-precision format is exactly 10737418/1073741824 or approximately 0.009999999776482582.
You should usually check equality in floating-point values using some small epsilon for variance.
public class Foo
{
//Choose a small value that is appropriate for your needs
//see the info below for some info from Microsoft
private static double epsilon = 0.00001;
private double defaultEfficiency = 100.0;
public double efficiencyBar = defaultEfficiency;
public bool IsBarAtDefaultValue()
{
//we use the absolute value of the difference. If this is smaller than
//epsilon, then the value is "good enough" for equal
if (Math.Abs(efficiencyBar - defaultEfficiency) < epsilon)
return true;
else
return false;
}
}
You could use something like Double.Epsilon
for your epsilon
value, but this is probably way too small for your needs and is recommended against in the documentation:
If you create a custom algorithm that determines whether two floating-point numbers can be considered equal, we do not recommend that you base your algorithm on the value of the Epsilon constant to establish the acceptable absolute margin of difference for the two values to be considered equal. (Typically, that margin of difference is many times greater than Epsilon.)
And in their documentation on the Double.Equals()
method:
Because Epsilon defines the minimum expression of a positive value whose range is near zero, the margin of difference between two similar values must be greater than Epsilon. Typically, it is many times greater than Epsilon. Because of this, we recommend that you do not use Epsilon when comparing Double values for equality.
Both places are good sources of additional information on comparing floating-point numbers safely.