我'我试图理解微软'的doubleutil . arecclose()代码,我反映了

本文关键字:代码 doubleutil 微软 arecclose | 更新日期: 2023-09-27 17:52:43

如果您在WindowsBase.dll > MS.Internal.DoubleUtil.AreClose(...)上进行反射,您将得到以下代码:

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));
}

我在试着理解两件不同的事情:

  1. 他们是怎么想出num2的公式的?我想我只是不明白首先将10.0的值相加然后将所有结果乘以这个数字2.2204460492503131E-16的意义。有人知道为什么用这个公式吗?

  2. 这里的return语句的意义是什么?似乎默认情况下,如果num2大于num那么num2的负值应该小于num,也许我在这里遗漏了什么,但这似乎是多余的。对我来说,这就像检查5是否大于3,如果-5小于3(作为一个例子)。

我'我试图理解微软'的doubleutil . arecclose()代码,我反映了

  1. 这似乎是一个基于所比较的数字的大小的"公差"值。请注意,由于浮点数的表示方式,指数为0的数字之间的最小可表示差异是2-53或大约1.11022 × 10-16。(参见维基百科上最后一个位置的单位和浮点数。)这里的常数恰好是该值的两倍,因此它允许在计算过程中累积的小舍入误差。

  2. 如果您重新排序条件中的参数,然后将num2重命名为tolerance,将num重命名为diff,应该会变得清晰。

即:

return ((-num2 < num) && (num2 > num));
return ((num > -num2) && (num < num2));
return ((diff > -tolerance) && (diff < tolerance));

注释应该有助于理解这个方法:)

/// <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)) &lt; DBL_EPSILON
    double eps = (Math.Abs(value1) + Math.Abs(value2) + 10.0) * DBL_EPSILON;
    double delta = value1 - value2;
    return (-eps < delta) && (eps > delta);
}

这里是"mystic"值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

在谷歌上搜索这个数字,我找到了这个页面http://en.m.wikipedia.org/wiki/Machine_epsilon

在图形学中,计算几何图形可能导致很小的两个点,从像素的角度来看可能非常接近。由于在按位计算时进行舍入,浮点数可能会给出很少不同的结果。这个方法检查一个数是否接近另一个在机器范围内的数。

我不知道为什么,但数字越接近0,差值必须越小才能通过检查。

对于小数,返回值是有意义的,例如0和1。如果没有第一部分,它将通过,但0和1不够接近:)