比较两个双精度浮点数或两个浮点数最有效的方法是什么?

简单地这样做是不正确的:

bool CompareDoubles1 (double A, double B)
{
   return A == B;
}

比如:

bool CompareDoubles2 (double A, double B) 
{
   diff = A - B;
   return (diff < EPSILON) && (-diff < EPSILON);
}

似乎是浪费加工。

有人知道更聪明的浮点比较器吗?


当前回答

这是另一个解:

#include <cmath>
#include <limits>

auto Compare = [](float a, float b, float epsilon = std::numeric_limits<float>::epsilon()){ return (std::fabs(a - b) <= epsilon); };

其他回答

在c++中获取的可移植方法是

#include <limits>
std::numeric_limits<double>::epsilon()

然后比较函数变成

#include <cmath>
#include <limits>

bool AreSame(double a, double b) {
    return std::fabs(a - b) < std::numeric_limits<double>::epsilon();
}

我对任何涉及浮点减法的答案都非常谨慎(例如,fabs(a-b) < epsilon)。首先,浮点数在更大的量级上变得更稀疏,在足够大的量级上,当间隔大于时,您可能只需要做a == b。其次,减去两个非常接近的浮点数(因为您正在寻找接近相等的浮点数)正是您得到灾难性抵消的方式。

虽然不能移植,但我认为grom的答案在避免这些问题方面做得最好。

这个怎么样?

template<typename T>
bool FloatingPointEqual( T a, T b ) { return !(a < b) && !(b < a); }

我见过各种方法,但从来没有见过这个,所以我也很好奇听到任何评论!

正如其他人所指出的那样,使用固定指数(例如0.0000001)对于远离该值的值是无用的。例如,如果你的两个值是10000.000977和10000,那么这两个数字之间没有32位浮点值——10000和10000.000977是你可能得到的最接近的值,而不是位对位相同。这里,小于0.0009是没有意义的;你也可以使用直接等式运算符。

同样地,当两个值的大小接近ε时,相对误差增长到100%。

Thus, trying to mix a fixed point number such as 0.00001 with floating-point values (where the exponent is arbitrary) is a pointless exercise. This will only ever work if you can be assured that the operand values lie within a narrow domain (that is, close to some specific exponent), and if you properly select an epsilon value for that specific test. If you pull a number out of the air ("Hey! 0.00001 is small, so that must be good!"), you're doomed to numerical errors. I've spent plenty of time debugging bad numerical code where some poor schmuck tosses in random epsilon values to make yet another test case work.

如果你从事任何类型的数值编程,并认为你需要达到定点的epsilon,请阅读BRUCE关于比较浮点数的文章。

浮点数比较

以更一般的方式:

template <typename T>
bool compareNumber(const T& a, const T& b) {
    return std::abs(a - b) < std::numeric_limits<T>::epsilon();
}

注意: 正如@SirGuy所指出的,这种方法是有缺陷的。 我把这个答案留在这里,作为一个不遵循的例子。