![](/img/trans.png)
[英]std::greater on a an std::pair of a double and a class
[英]Is std::greater<double> and std::less<double> safe to use?
當比較C ++中的double
值時,使用<,>,=,!=
運算符,我們無法始終確定結果的正確性。 這就是為什么我們使用其他技術來比較doubles
,例如,我們可以通過測試它們的差異是否真的接近零來比較兩個雙打a和b。 我的問題是,C ++標准庫是否使用這些技術實現了std::less<double>
和std::greater<double>
,還是只使用了不安全的比較運算符?
您可以100%確定這些運算符的結果的正確性。 只是先前的計算可能導致截斷,因為雙精度的精度不是無窮無盡的。 所以操作員完全沒問題,只是你的操作數不是你所期望的那樣。
所以你用什么來比較並不重要。
他們使用標准運營商。 以下是stl_function.h頭文件中std :: greater的定義
templatete<typename _Tp>
struct greater : public binary_function<_Tp, _Tp, bool>
{
bool
operator()(const _Tp& __x, const _Tp& __y) const
{ return __x > __y; }
};
operator<
和operator>
確實給出了正確的結果,至少盡可能。 然而,使用浮點算術有一些基本問題,特別是double
。 使用您提到的比較函數不會減少這些因素,因為它們是當前CPU使用的浮點表示所固有的。
至於函數std::less
/ std::greater
:它們只是標准運算符的打包版本,旨在在STL算法中需要二進制謂詞時使用。
double
值具有64位表示,而Intel CPU的原始“double”算法以80位完成。 聽起來很擅長“免費”獲得更高的精度,但這也意味着結果取決於編譯器是否允許代碼直接從FPU寄存器(80位)或寫回內存的值使用中間結果(四舍五入到64位)。 這種優化完全取決於編譯器,並且不受任何標准的定義。
為了使事情變得更復雜,現代編譯器也可以使用更新的向量指令(MMX / SSE),它們也只是64位。 上述問題不會出現在這種情況下。 但是,它依賴於編譯器是否將這些指令用於浮點算術。
當差異僅在尾數的最后幾位時,總是會比較少於/大於幾乎相等的值 - 它們總是會受到截斷錯誤的影響,並且你應該確保你的程序不會嚴重依賴於非常接近的值的比較。 例如,當它們的差值小於閾值時,可以考慮它們相等,例如if (fabs(a - b)/a < factor*DBL_EPSILON) { /* EQUAL */ }
。 DBL_EPSILON
在float.h
中定義, factor
取決於先前已經進行了多少次可能的截斷/舍入的數學運算,應該進行徹底的測試。 我的安全值大約factor=16..32
,但你的里程可能會有所不同。
從cppreference它說
使用operator <on類型T.
這意味着除非有一個operator<
或operator>
你在double
上專門重載以實現正確的比較,否則使用std::less
或std::greater
會對你沒有適當的比較。
督察可以使用std::greater
或std::less
,但除非你去實現一些將使用標准比較operator<
或operator>
專門來比較double
S或float
s請正確使用它們的差值小於std::numeric_limits<double>::epsilon()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.