Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I'm trying to understand Microsoft's DoubleUtil.AreClose() code that I reflected over

If you reflect over WindowsBase.dll > MS.Internal.DoubleUtil.AreClose(...) you'll get the following code:

public static bool AreClose(double value1, double value2)
{
    if (value1 == value2)
    {
        return true;
    }
    double num2 = ((Math.Abs(value1) + Math.Abs(value2)) + 10.0) * 2.2204460492503131E-16;
    double num = value1 - value2;
    return ((-num2 < num) && (num2 > num));
}

I'm trying to understand two different things:

  1. Where did they come up with the formula for num2? I guess I just don't understand the significance of first adding the value of 10.0 and secondly multiplying all the results by this the number 2.2204460492503131E-16. Anyone know why this is the formula used?

  2. What is the point of the return statement there? It seems that by default if num2 greater than num than the negated value of num2 should be less than num. Maybe I'm missing something here, but it seems redundant. To me it's like checking if 5 is larger than 3 and if -5 is less than 3 (as an example).

like image 350
myermian Avatar asked Apr 22 '11 18:04

myermian


1 Answers

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

  2. If you reorder the parameters in the conditionals, and then rename num2 to tolerance and num to diff, it should become clear.

Viz.:

return ((-num2 < num) && (num2 > num));
return ((num > -num2) && (num < num2));
return ((diff > -tolerance) && (diff < tolerance));
like image 174
Bradley Grainger Avatar answered Oct 12 '22 02:10

Bradley Grainger