繁体   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