Double.Epsilon for equality, greater than, less than, less than or equal to, greater than or equal to

http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx

If you create a custom algorithm that determines whether two floating-point numbers can be considered equal, you must use a value that is greater than 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.)

So is this not really an epsilon that could be used for comparisons? I don't really understand the MSDN wording.

Can it be used as the epsilon in the examples here? - What is the most effective way for float and double comparison?

And finally this seems really important so I'd like to make sure I have a solid implementation for equality, greater than, less than, less than or equal to, and greater than or equal to.


I don't know what they were smoking when they wrote that. Double.Epsilon is the smallest representable non-denormal floating point value that isn't 0. All you know is that, if there's a truncation error, it will always be larger than this value. Much larger.

The System.Double type can represent values accurate to up to 15 digits. So a simple first order estimate if a double value x is equal to some constant is to use an epsilon of constant * 1E-15

public static bool AboutEqual(double x, double y) {
    double epsilon = Math.Max(Math.Abs(x), Math.Abs(y)) * 1E-15;
    return Math.Abs(x - y) <= epsilon;
}

You have to watch out though, truncation errors can accumulate. If both x and y are computed values then you have to increase the epsilon.


I'd like to make sure I have a solid implementation for equality, greater than, less than, less than or equal to, and greater than or equal to.

You are using binary floating point arithmetic.

Binary floating point arithmetic was designed to represent physical quantities like length, mass, charge, time, and so on.

Presumably then you are using binary floating point arithmetic as it was intended to be used: to do arithmetic on physical quantities.

Measurements of physical quantities always have a particular precision, depending on the precision of the device used to measure them.

Since you are the one providing the values for the quantities you are manipulating, you are the one who knows what the "error bars" are on that quantity. For example, if you are providing the quantity "the height of the building is 123.56 metres" then you know that this is accurate to the centimetre, but not to the micrometer.

Therefore, when comparing two quantities for equality, the desired semantics is to say "are these two quantities equal within the error bars specified by each measurement?"

So now we have an answer to your question. What you must do is keep track of what the error is on each quantity; for example, the height of the building is "within 0.01 of 123.56 meters" because you know that is how precise the measurement is. If you then get another measurement which is 123.5587 and want to know whether the two measurements are "equal" within error tolerances, then do the subtraction and see if it falls into the error tolerance. In this case it does. If the measurements were in fact precise to the micrometre, then they are not equal.

In short: you are the only person here who knows what sensible error tolerances are, because you are the only person who knows where the figures you are manipulating came from in the first place. Use whatever error tolerance makes sense for your measurements given the precision of the equipment you used to produce it.


If you have two double values that are close to 1.0, but they differ in only their least significant bits, then the difference between them will be many orders of magnitude greater than Double.Epsilon. In fact, the difference is 324 decimal orders of magnitude. This is because of the effect of the exponent portion. Double.Epsilon has a huge negative exponent on it, while 1.0 has an exponent of zero (after the biases are removed, of course).

If you want to compare two similar values for equality, then you will need to choose a custom epsilon value that is appropriate for the orders-of-magnitude size of the values to be compared.

If the double values that you are comparing are near 1.0. Then the value of the least siginificant bit would be near 0.0000000000000001. If the double values that you are comparing are in the quadrillions, then the value of the least significant bit could be as much as a thousand. No single value for epsilon could be used for equality comparisons in both of those circumstances.