【问题标题】:Double.Epsilon for equality, greater than, less than, less than or equal to, greater than or equal toDouble.Epsilon 表示相等,大于、小于、小于或等于、大于或等于
【发布时间】:2011-01-25 13:35:07
【问题描述】:

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

如果您创建一个自定义算法, 判断两个浮点数 数字可以被认为是相等的,你 必须使用大于 Epsilon 常数建立 可接受的绝对裕度 两个值的差异为 认为相等。 (通常情况下, 差距是很多倍 大于 Epsilon。)

所以这不是一个可以用于比较的真正的 epsilon 吗?我不太明白 MSDN 的措辞。

可以在这里的示例中用作 epsilon 吗? - What is the most effective way for float and double comparison?

最后,这似乎真的很重要,所以我想确保我有一个可靠的相等实现,大于、小于、小于或等于,以及大于或等于。

【问题讨论】:

    标签: c# epsilon


    【解决方案1】:

    我不知道他们写这篇文章时什么Double.Epsilon 是最小的非 0 非反规范浮点值。您所知道的是,如果出现截断错误,它总是会大于这个值。更大。

    System.Double 类型可以表示精确到 15 位的值。因此,如果双精度值 x 等于某个常数,简单的一阶估计是使用常数 * 1E-15 的 epsilon

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

    您必须小心,截断错误可能会累积。如果 xy 都是计算值,那么您必须增加 epsilon。

    【讨论】:

    • 微软说Represents the smallest positive Double value that is greater than zero.msdn.microsoft.com/en-us/library/…
    • @Ian Double.Epsilon 应该是这样,但 david.pfx 将其定义为 :-(
    • 1.0 + double.Epsilon = 1.0
    • 1.0 + 1E-16 = 1.0,还有很多 :)
    • 啧啧啧,有经验的程序员做出这样的陈述确实解释了为什么我们会收到这么多关于这个话题的问题。基数 2 != 基数 10。
    【解决方案2】:

    我想确保我对相等、大于、小于、小于或等于以及大于或等于有一个可靠的实现。

    您正在使用二进制浮点运算。

    二进制浮点运算旨在表示长度、质量、电荷、时间等物理量。

    大概那么您正在使用二进制浮点算术,因为它打算用于:对物理量进行算术。

    物理量的测量总是具有特定的精度,具体取决于用于测量它们的设备的精度。

    由于您是为您正在操作的数量提供值的人,因此您知道该数量的“误差线”是什么。例如,如果您提供的数量是“建筑物的高度是 123.56 米”,那么您就知道这是精确到厘米,而不是精确到微米。

    因此,当比较两个量是否相等时,所需的语义是“这两个量在每次测量指定的误差线内是否相等?”

    所以现在我们已经回答了您的问题。您必须做的是跟踪每个数量的错误;例如,建筑物的高度“在 123.56 米的 0.01 范围内”,因为您知道测量的精确度。如果您随后获得另一个测量值 123.5587,并且想知道这两个测量值在误差容限内是否“相等”,那么请进行减法并查看它是否属于误差容限。在这种情况下,它确实如此。如果测量结果实际上精确到微米,那么它们就不相等。

    简而言之:你是这里唯一知道什么是合理误差容限的人,因为你是唯一知道你所操纵的数字首先来自哪里的人。考虑到您用于生产测量的设备的精度,请使用对您的测量有意义的任何误差容限。

    【讨论】:

    • 虽然指出公差是一种更实际和更直接的定义方法当然是正确的,但我正在调查编码表示的不准确性作为一般的第一遍规则,而公差将是可选的第二遍,具体取决于具体情况。
    • Eric,如果您创建某种数据结构(例如游戏)并希望允许其他游戏使用它,每个人都会有不同的容忍度,因为他们都使用不同的坐标系。所以,我认为,决定你的 epsilon 是什么,不仅仅是个人条件的问题。
    • 您没有回答问题。这不是品味或上下文的问题,它与内存中双精度数的定义有关(IEEE 754)。
    • 浮点值经常用于基于物理测量技术的没有误差线的综合计算。了解数据类型的精度限制对于许多问题都很重要。
    【解决方案3】:

    如果您有两个接近 1.0 的 double 值,但它们仅在最低有效位上有所不同,那么它们之间的差异将比 Double.Epsilon 大许多数量级。事实上,差异是 324 个十进制数量级。这是因为指数部分的影响。 Double.Epsilon 有一个巨大的负指数,而 1.0 的指数为零(当然是在消除偏差之后)。

    如果您想比较两个相似的值是否相等,则需要选择适合要比较的值的数量级大小的自定义 epsilon 值。

    如果您要比较的双精度值接近 1.0。那么最低有效位的值将接近 0.0000000000000001。如果您要比较的双精度值是千万亿,那么最低有效位的值可能高达一千。在这两种情况下,没有一个 epsilon 值可用于相等比较。

    【讨论】:

      【解决方案4】:

      我只是这样做了 - 使用 Kent Bogarts 的想法。

      private bool IsApproximatelyEqual(double x, double y, double acceptableVariance)
      {
           double variance = x > y ? x - y : y - x;
           return variance < acceptableVariance;
      
           //or
           //return Math.Abs(x - y) < acceptableVariance;
      }
      

      【讨论】:

        【解决方案5】:

        它可以用于比较,假设您要确保两个值完全相等,或者对于 double 类型具有最小的可表示差异。一般来说,您会希望使用大于double.Epsilon 的数字来检查两个双精度数是否近似相等。

        为什么 .NET 框架没有定义类似的东西

        bool IsApproximatelyEqual(double value, double permittedVariance);
        

        超出了我的范围。

        【讨论】:

          【解决方案6】:

          我用下面的

          public static class MathUtil {
              /// <summary>
              /// smallest such that 1.0+EpsilonF != 1.0
              /// </summary>
              public const float EpsilonF = 1.192092896e-07F;
          
              /// <summary>
              /// smallest such that 1.0+EpsilonD != 1.0
              /// </summary>
              public const double EpsilonD = 2.2204460492503131e-016;
          
              [MethodImpl( MethodImplOptions.AggressiveInlining )]
              public static bool IsZero( this double value ) {
                  return value < EpsilonD && value > -EpsilonD;
              }
          
              [MethodImpl( MethodImplOptions.AggressiveInlining )]
              public static int Sign( this double value ) {
                  if ( value < -EpsilonD ) {
                      return -1;
                  }
                  if ( value > EpsilonD )
                      return 1;
                  return 0;
              }
          

          如果你想检查两个双打'a'和'b'是否相等,你可以使用

          (a-b).IsZero();
          

          如果你想得到比较结果,使用

          (a-b).Sign();
          

          【讨论】:

          • 通常 epsilon 与两个减法绝对值中的较大者相乘,因为 epsilon 取决于较大的操作数。
          【解决方案7】:

          比较双精度的问题在于,当您在两个不同的数学结果之间进行比较时,它们相等但由于舍入误差而未计算为相同的值,它们会有一些差异......这是大于 epsilon,除了边缘情况。并且使用可靠的 epsilon 值也很困难。如果两个双精度值之间的差异小于某个百分比值,则有些人认为它们相等,因为使用静态最小差异 epsilon 可能意味着当双精度值本身高或低时您的差异太小或太大。

          【讨论】:

            【解决方案8】:

            以下是 Silverlight 控制工具包中包含两次的一些代码:

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

            他们在一个地方使用1e-6 表示epsilon;在另一个他们使用1.192093E-07。您将需要选择自己的 epsilon。

            【讨论】:

            • 这个看起来很有希望。看起来他们在比较高值时解决了小数精度降低的问题。当然,你必须考虑你是否想要这种精度缩放。它与带有静态 epsilon 的版本一样适用。
            【解决方案9】:

            没有选择你必须自己计算或定义自己的常数。

            double calculateMachineEpsilon() {
                double result = 1.0;
                double one = 1.0/256;
            
                while(one + result/2.0 != 1.0) {
                    result/=2.0;
                }
                return result;
            }
            

            【讨论】:

              猜你喜欢
              • 2013-09-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-12-17
              • 1970-01-01
              • 1970-01-01
              • 2012-09-11
              • 2011-12-21
              相关资源
              最近更新 更多