4 回答

TA貢獻1827條經驗 獲得超9個贊
使用任何其他建議時要格外小心。這一切都取決于背景。
我花了很長時間跟蹤系統中的錯誤,假設a==b
是|a-b|<epsilon
。潛在的問題是:
算法中隱含的假設,if
a==b
和b==c
thena==c
。使用相同的epsilon測量以英寸為單位的線和以mils(.001英寸)測量的線。那是
a==b
但是1000a!=1000b
。(這就是AlmostEqual2sComplement要求epsilon或max ULPS的原因)。對于角度的余弦和線的長度,使用相同的epsilon!
使用這樣的比較函數對集合中的項目進行排序。(在這種情況下,使用內置C ++運算符== for double產生了正確的結果。)
就像我說:這一切都取決于背景和預期的大小a
和b
。
BTW,std::numeric_limits<double>::epsilon()
是“機器epsilon”。它是1.0和下一個值之間的差值,可用雙精度表示。我猜它可以在比較函數中使用,但只有在預期值小于1時才會使用。(這是對@ cdv答案的回應......)
另外,如果你基本上有int
算術doubles
(這里我們使用雙精度來保存某些情況下的int值)你的算術是正確的。例如,4.0 / 2.0將與1.0 + 1.0相同。只要您不執行導致分數(4.0 / 3.0)或不超出int大小的事情。

TA貢獻1854條經驗 獲得超8個贊
有關更深入的方法,請參閱比較浮點數。以下是該鏈接的代碼段:
// Usable AlmostEqual function bool AlmostEqual2sComplement(float A, float B, int maxUlps) { // Make sure maxUlps is non-negative and small enough that the // default NAN won't compare as equal to anything. assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024); int aInt = *(int*)&A; // Make aInt lexicographically ordered as a twos-complement int if (aInt < 0) aInt = 0x80000000 - aInt; // Make bInt lexicographically ordered as a twos-complement int int bInt = *(int*)&B; if (bInt < 0) bInt = 0x80000000 - bInt; int intDiff = abs(aInt - bInt); if (intDiff <= maxUlps) return true; return false; }
添加回答
舉報