简体   繁体   English

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

[英]Is std::greater<double> and std::less<double> safe to use?

When comparing double values in C++, using the <,>,=,!= operators, we cannot always be sure about correctness of the result. 当比较C ++中的double值时,使用<,>,=,!=运算符,我们无法始终确定结果的正确性。 Thats why we use other techniques to compare doubles , for example, we can compare two doubles a and b by testing if their difference is really close to zero. 这就是为什么我们使用其他技术来比较doubles ,例如,我们可以通过测试它们的差异是否真的接近零来比较两个双打a和b。 My question is, does the C++ standard library implements std::less<double> and std::greater<double> using these techniques, or it just uses the unsafe comparison operators? 我的问题是,C ++标准库是否使用这些技术实现了std::less<double>std::greater<double> ,还是只使用了不安全的比较运算符?

You can be a 100% sure about the correctness of the result of those operators. 您可以100%确定这些运算符的结果的正确性。 It's just that a prior calculation may have resulted in truncation because precision of a double is not endless. 只是先前的计算可能导致截断,因为双精度的精度不是无穷无尽的。 So the operators are perfectly fine, just your operands are not what you expected them to be. 所以操作员完全没问题,只是你的操作数不是你所期望的那样。

So it does not matter what you use for comparison. 所以你用什么来比较并不重要。

They use standard operators. 他们使用标准运营商。 Here is the definition of std::greater in stl_function.h header file 以下是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< and operator> do give the correct result, at least as far as possible. operator<operator>确实给出了正确的结果,至少尽可能。 However, there are some fundamental problems involved with using floating point arithmetics, especially double . 然而,使用浮点算术有一些基本问题,特别是double These are not reduced by using the comparison functions you mention, as they are inherent to the floating point representation used by current CPUs. 使用您提到的比较函数不会减少这些因素,因为它们是当前CPU使用的浮点表示所固有的。

As for the functions std::less / std::greater : They are just packaged versions of the standard operators, intended to be used when a binary predicate is needed in STL algorithms. 至于函数std::less / std::greater :它们只是标准运算符的打包版本,旨在在STL算法中需要二进制谓词时使用。

A double value has a 64 bit representation, whereas the Intel CPUs' original "double" arithmetic is done in 80 bits. double值具有64位表示,而Intel CPU的原始“double”算法以80位完成。 Sounds good at first to get some more precision "for free", but it also means that the result depends on whether the compiler lets the code use intermediate results directly from the FPU registers (in 80 bits) or from the values written back to memory (rounded to 64 bit). 听起来很擅长“免费”获得更高的精度,但这也意味着结果取决于编译器是否允许代码直接从FPU寄存器(80位)或写回内存的值使用中间结果(四舍五入到64位)。 This kind of optimization is completely up to the compiler and isn't defined by any standard. 这种优化完全取决于编译器,并且不受任何标准的定义。

To make things more complex, modern compilers can also make use of the newer vector instructions (MMX / SSE), which again are 64 bits only. 为了使事情变得更复杂,现代编译器也可以使用更新的向量指令(MMX / SSE),它们也只是64位。 The problems described above do not appear in this context. 上述问题不会出现在这种情况下。 However, it depends on the compiler whether it makes use of these instructions for floating point arithmetics. 但是,它依赖于编译器是否将这些指令用于浮点算术。

Comparisons for less/greater of almost equal values always will suffer when the difference is only in the last bits of the mantissa -- they are always subject to truncation errors, and you should make sure that your program does not critically rely on the result of a comparison of very close values. 当差异仅在尾数的最后几位时,总是会比较少于/大于几乎相等的值 - 它们总是会受到截断错误的影响,并且你应该确保你的程序不会严重依赖于非常接近的值的比较。 You can for example considering them equal when their difference is less than a threshold, eg by if (fabs(a - b)/a < factor*DBL_EPSILON) { /* EQUAL */ } . 例如,当它们的差值小于阈值时,可以考虑它们相等,例如if (fabs(a - b)/a < factor*DBL_EPSILON) { /* EQUAL */ } DBL_EPSILON is defined in float.h , and factor depends on how many mathematical operations with possible truncation/rounding have been made previously, and should be tested thoroughly. DBL_EPSILONfloat.h中定义, factor取决于先前已经进行了多少次可能的截断/舍入的数学运算,应该进行彻底的测试。 I've been safe with values around factor=16..32 , but your mileage may vary. 我的安全值大约factor=16..32 ,但你的里程可能会有所不同。

From cppreference it says cppreference它说

Uses operator< on type T. 使用operator <on类型T.

Meaning that unless there's an operator< or operator> you have specifically overloaded on double to implement proper comparison, there is going to be NO proper comparison extant for you using std::less or std::greater . 这意味着除非有一个operator<operator>你在double上专门重载以实现正确的比较,否则使用std::lessstd::greater会对你没有适当的比较。

IOW you can use std::greater or std::less but it will use standard comparison unless you go implement some operator< or operator> specifically to compare double s or float s properly using their difference less than std::numeric_limits<double>::epsilon() 督察可以使用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