2012-01-02 73 views
4

起初我以为我只能依靠最大的相对差异,但我错了。例如,如果a = 0.0b = 0.5,它们的相对差异是1.0。在这种情况下,approxEquals(lhs, rhs, maxRelDiff, maxAbsDiff)依赖最大绝对差来确定两个浮点数是否相等。approxEqual()的正确用法是什么?

两个问题是:

  1. 我怎么想出了一个新的最大相对和绝对差对如果默认(1E-2,1E-5)是不够严谨? 1e-21e-5如何被选为默认值?例如,如果我选择1e-4作为我的最大相对差异,那么最大绝对差异是多少?

  2. 如何调整最大相对和绝对差值以便与floatsdoubles正常工作?

回答

0

虽然我不能回答你原来的问题,我个人只是用fabs用于浮点比较:

return fabs(f1 - f2) < 0.10; 
+1

你计算'绝对difference',并将其与对'0.10'。你不能只依靠绝对的差异,而你的'0.10'在大多数情况下都不够小。 – Arlen 2012-01-02 02:36:36

+0

如果f1 = 0.01和f2 = 0.03,你有相当大的相对差异,但你的表达会说“他们是相同的”。 – 2012-01-02 04:02:30

+0

为了某些代码的目的,这是我想要的行为。 – 2012-01-02 16:21:03

1

检查source code给我这个(我剪下实现的范围)

bool approxEqual(T, U, V)(T lhs, U rhs, V maxRelDiff, V maxAbsDiff = 1e-5) 
{ 

    if (rhs == 0) 
    { 
     return fabs(lhs) <= maxAbsDiff; 
    } 
    static if (is(typeof(lhs.infinity)) && is(typeof(rhs.infinity))) 
    { 
     if (lhs == lhs.infinity && rhs == rhs.infinity || 
      lhs == -lhs.infinity && rhs == -rhs.infinity) return true; 
    } 
    return fabs((lhs - rhs)/rhs) <= maxRelDiff 
     || maxAbsDiff != 0 && fabs(lhs - rhs) <= maxAbsDiff; 
} 

最后一行是我们将要研究:

return fabs((lhs - rhs)/rhs) <= maxRelDiff 
     || maxAbsDiff != 0 && fabs(lhs - rhs) <= maxAbsDiff; 

换句话说,如果编号是要么相对不同决不该函数返回true多于不超过maxAbsDiff

所以使用0.01maxRelDiff一个的maxRelDiff OR 绝对不同因子(或1E-2)与2(十进制)数字的精确度进行比较

并且使用maxAbsDiff不同于0允许接近于0的数字被认为是相等的,即使相对差异更大比maxRelDiff

编辑:基本上先决定比较如何准确的必须,并选择您maxRelDiff基于这一点,那么在什么时候决定应该在数等于0

与注释的例子:

approxEqual(1+1e-10, 1.0, 1e-10, 1e-30) 
approxEqual(1+1e-10, 1.0, 1e-9, 1e-30) 

这比较接近1,因此maxRelDiff胜过这里的价值观和选择任何maxAbsDiff(低于maxRelDiff)不会改变任何东西

approxEqual(0, 1e-10, 1e-10, 1e-30) 
approxEqual(0, 1e-9, 1e-9, 1e-30) 

这比较接近0值设置为0,因此RelDiff(fabs((lhs - rhs)/rhs))将1和maxAbsDiff胜过

+0

谢谢,但我非常了解Phobos中的实现。是的,该函数使用'maxRelDiff'或'maxAbsDiff',但你错过了这一点。这些问题不是关于'approxEqual()'是如何工作的。相反,我想知道如何选择与Phobos中使用的默认值不同的'maxRelDiff'和'maxAbsDiff'对。我也想扩大这对,以便用'浮动'和'双打'来正常工作。 – Arlen 2012-01-02 04:33:54

+0

只是为了说明为什么需要仔细选择这对:“近似等于(1 + 1e-10,1.0,1e-10,1e-30)”和“近似等于(1 + 1e-10,1.0,1e- (0,1e-10,1e-10,1e-30)'和'approxEqual(0,1e-30)'不会影响maxRelDiff和maxAbsDiff的值选择, 9,1e-9,1e-30)。 – Arlen 2012-01-02 04:38:06

+0

花花公子最后的段落仔细阅读,我添加了一点explenation – 2012-01-02 13:32:11