簡體   English   中英

是否可以使用std :: greater <double>和std :: less <double>?

[英]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_EPSILONfloat.h中定義, factor取決於先前已經進行了多少次可能的截斷/舍入的數學運算,應該進行徹底的測試。 我的安全值大約factor=16..32 ,但你的里程可能會有所不同。

cppreference它說

使用operator <on類型T.

這意味着除非有一個operator<operator>你在double上專門重載以實現正確的比較,否則使用std::lessstd::greater會對你沒有適當的比較。

督察可以使用std::greaterstd::less ,但除非你去實現一些將使用標准比較operator<operator>專門來比較double S或float s請正確使用它們的差值小於std::numeric_limits<double>::epsilon()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM