比较 2 个双精度值的正确方法是什么?

What is correct way to compare 2 doubles values?

这里有很多关于这个主题的文章、博士出版物、书籍和问题,我的问题仍然很简单。

我们如何在不编写几十个 ifs 的情况下改进这个或解决方法?

假设我有 2 个双打;

double d1 = ..;
double d2 = ..;

我们可以尝试做的最天真的想法就是尝试 if(d1==d2) // baaaad!!!,因为我们知道我们可能会在非常接近的值上出现精度不匹配而失败。

第二个天真的事情可以是if(std::abs(d1-d2) < std::numeric_limits<double>::epsilon())
对于相对较大的双打,这仍然失败,因为 std::numeric_limits<double>::epsilon() 描述如下:

Returns the machine epsilon, that is, the difference between 1.0 and the next value representable by the floating-point type T

双倍的是0.00000000000000022204

所以我想到了这个:

double epsilon = std::max(d1,d2)/1E14; // 我可以接受第 14 位后的精度不匹配,无论数字有多大。

这里的问题是对于小数字这会失败,例如打印 0.00..00

double d = 1E-7;  
std::cout<<std::fixed<<std::setprecision(20)<< d/1E14;

所以问题是是否有一个通用的 solution/workaround,或者我应该写几十个 ifs 来正确地决定我的面额,以免过度精确?

So the question will be is there a generic solution/workaround for this

不会有适用于所有用例的有限精度浮点的通用解决方案。不可能,因为每次计算的正确阈值都是特定的,一般不能自动知道。

你必须知道你在比较什么以及你期望从比较中得到什么。完整的解释不适合这个答案,但你可以从这个博客中找到大部分信息:https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/(不是我的)。


但是有一个通用的 solution/workaround side-steps 问题:使用无限精度算术。 C++标准库没有提供无限精度算术的实现。