I'm trying to understand Microsoft's DoubleUtil.AreClose() code that I reflected over
This appears to be a "tolerance" value that's based on the magnitude of the numbers being compared. Note that due to how floating point numbers are represented, the smallest representable difference between numbers with an exponent of 0 is 2-53 or approximately 1.11022 × 10-16. (See unit in the last place and floating point on Wikipedia.) The constant here is exactly two times that value, so it allows for small rounding errors that have accumulated during computations.
If you reorder the parameters in the conditionals, and then rename
num2
totolerance
andnum
todiff
, it should become clear.
Viz.:
return ((-num2 < num) && (num2 > num));
return ((num > -num2) && (num < num2));
return ((diff > -tolerance) && (diff < tolerance));
The comments should help understanding this method :)
/// <summary>
/// AreClose - Returns whether or not two doubles are "close". That is, whether or
/// not they are within epsilon of each other. Note that this epsilon is proportional
/// to the numbers themselves to that AreClose survives scalar multiplication.
/// There are plenty of ways for this to return false even for numbers which
/// are theoretically identical, so no code calling this should fail to work if this
/// returns false. This is important enough to repeat:
/// NB: NO CODE CALLING THIS FUNCTION SHOULD DEPEND ON ACCURATE RESULTS - this should be
/// used for optimizations *only*.
/// </summary>
/// <returns>
/// bool - the result of the AreClose comparision.
/// </returns>
/// <param name="value1"> The first double to compare. </param>
/// <param name="value2"> The second double to compare. </param>
public static bool AreClose(double value1, double value2)
{
// in case they are Infinities (then epsilon check does not work)
if (value1 == value2)
{
return true;
}
// This computes (|value1-value2| / (|value1| + |value2| + 10.0)) < DBL_EPSILON
double eps = (Math.Abs(value1) + Math.Abs(value2) + 10.0) * DBL_EPSILON;
double delta = value1 - value2;
return (-eps < delta) && (eps > delta);
}
Update
And here the "mystic" value DBL_EPSILON
// Const values come from sdk\inc\crt\float.h
internal const double DBL_EPSILON = 2.2204460492503131e-016; /* smallest such that 1.0+DBL_EPSILON != 1.0 */
src
Searching on google for that number lead me to this page http://en.m.wikipedia.org/wiki/Machine_epsilon
In graphics, calculating geometry can result in little two points which may be very close from pixel point of view. Since floating point numbers may give little different result due to rounding done at bitwise calculation. So this method checks if number is close to another number within range of machine epsilon.