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

时间:2013-08-06 08:06:49

标签: c++ double floating-point-precision

在使用double运算符比较C ++中的<,>,=,!=值时,我们无法始终确定结果的正确性。这就是为什么我们使用其他技术来比较doubles,例如,我们可以通过测试它们的差异是否真的接近零来比较两个双打a和b。我的问题是,C ++标准库是否使用这些技术实现std::less<double>std::greater<double>,还是只使用不安全的比较运算符?

4 个答案:

答案 0 :(得分:10)

您可以100%确定这些运营商的结果的正确性。只是先前的计算可能导致截断,因为双精度的精度不是无穷无尽的。所以操作员完全没问题,只是你的操作数不是你所期望的那样。

所以你用什么来比较并不重要。

答案 1 :(得分:4)

他们使用标准运营商。以下是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; }
    };

答案 2 :(得分:4)

operator<operator>确实给出了正确的结果,至少尽可能的。但是,使用浮点算术有一些基本问题,尤其是double。使用您提到的比较函数不会减少这些因素,因为它们是当前CPU使用的浮点表示所固有的。

对于函数std::less / std::greater:它们只是标准运算符的打包版本,旨在在STL算法中需要二进制谓词时使用。

double值具有64位表示,而Intel CPU的原始“双”算术以80位完成。听起来很擅长“免费”获得更高的精度,但这也意味着结果取决于编译器是否允许代码直接从FPU寄存器(80位)或写回内存的值使用中间结果(四舍五入到64位)。这种优化完全取决于编译器,并且没有任何标准定义。

为了使事情变得更复杂,现代编译器也可以使用更新的向量指令(MMX / SSE),它们也只是64位。上述问题不会出现在这种情况下。但是,它依赖于编译器是否将这些指令用于浮点算术。

当差异仅在尾数的最后几位时,总是会比较几乎相等的值的更少/更多 - 它们总是会受到截断错误的影响,并且你应该确保你的程序不会严重依赖于非常接近的值的比较结果。例如,当它们的差值小于阈值时,例如可以将它们视为相等,例如,按if (fabs(a - b)/a < factor*DBL_EPSILON) { /* EQUAL */ }DBL_EPSILON中定义了float.h,而factor取决于先前已经进行了多少次可能截断/舍入的数学运算,应该进行彻底测试。我对factor=16..32左右的值很安全,但你的里程可能会有所不同。

答案 3 :(得分:3)

来自cppreference它说

  

使用运算符&lt;在类型T上。

这意味着除非operator<operator>double上专门重载以实现正确的比较,否则使用{{1}将无法进行适当的比较}或std::less

以下您可以使用std::greaterstd::greater但它会使用标准比较,除非您专门实施一些std::lessoperator<来比较operator>double正确使用差异小于float