2012-01-02 22 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