C++ 比较浮点Nos-Google测试框架

C++ 比较浮点Nos-Google测试框架,c++,floating-point,floating-accuracy,C++,Floating Point,Floating Accuracy,用户@skrebbel在浏览SO的帖子时表示,google测试框架在比较浮动和双精度方面做得又好又快。所以我写了下面的代码来检查代码的有效性,显然我在这里遗漏了一些东西,因为我希望在这里输入几乎等于的部分,这是我的代码 float left = 0.1234567; float right= 0.1234566; const FloatingPoint<float> lhs(left), rhs(right); if (lhs.AlmostEquals(rhs)) {

用户@skrebbel在浏览SO的帖子时表示,google测试框架在比较浮动和双精度方面做得又好又快。所以我写了下面的代码来检查代码的有效性,显然我在这里遗漏了一些东西,因为我希望在这里输入几乎等于的部分,这是我的代码

float left = 0.1234567;
float right= 0.1234566;

const FloatingPoint<float> lhs(left), rhs(right);


if (lhs.AlmostEquals(rhs)) 
{
    std::cout << "EQUAL"; //Shouldnt it have entered here ?
}
float left=0.1234567;
右浮动=0.1234566;
常量浮动点左侧(左),右侧(右);
if(左侧阿尔莫斯特奎尔斯(右侧))
{
std::cout您可以使用

ASSERT_NEAR(val1, val2, abs_error); 

如果您可以将可接受的-您选择的一个,比如说0.0000001-差异作为
abs\u error
,如果默认值太小,请参见此处您的
不“几乎相等”因为它们之间的距离太远,超出了默认公差
AlmostEquals
。您链接到的问题中的一个答案中的代码显示公差为4 ULP,但您的数字之间的距离为14 ULP(使用IEEE 754 32位二进制和正确舍入软件)。(ULP是浮点值的最小增量。对于大小较小的浮点数,ULP较小;对于较大的浮点数,ULP较大,因此ULP与数字的大小近似相关。)

如果不了解正在比较的值中可能存在的错误以及正在执行的比较,则决不能执行任何浮点比较

人们经常错误地说不能测试浮点值是否相等。这是错误的;执行
a==b
是一个完美的操作。当且仅当
a
等于
b
(即
a
b
是值完全相同的数字)时,才会返回true。实际的问题是,他们试图在输入错误的情况下计算正确的函数。
=
是一个函数:它接受两个输入并返回一个值。显然,如果给任何函数错误的输入,它可能返回错误的结果。因此,这里的问题不是浮点比较;它是不正确的inputs。如果输入不正确,通常无法正确计算和、积、平方根、对数或任何其他函数。因此,使用浮点时,必须设计一种算法来处理近似值(或在特殊情况下,非常小心以确保不会引入错误)

通常,人们试图通过接受稍有不同的相等数字来解决浮点值中的错误。这减少了误报(由于先前的计算错误而导致的不平等迹象),但增加了误报(由于接受不严而导致的相等迹象)。将一种错误转换为另一种错误是否可以接受取决于应用程序。没有通用的解决方案,这就是为什么像
AlmostEquals
这样的函数通常是不好的

浮点值中的错误是前面的操作和值的结果。这些错误的范围可以从零到无穷大,具体取决于环境。因此,决不能简单地接受函数的默认公差,例如
AlmostEquals
。相反,应计算特定于他们的应用、需求和计算,并使用计算出的公差(或根本不使用比较)

另一个问题是,诸如
AlmostEquals
之类的函数通常是使用相对于所比较的值指定的公差来编写的。然而,值中的误差可能受到大小相差很大的中间值的影响,因此最终误差可能是函数中不存在的数据的函数正在比较的值


“近似值”在测试其他代码的代码中,浮点比较可能是可以接受的,因为大多数错误可能会导致较大的错误,因此对相等性的不严格接受将允许好代码继续,但会报告大多数坏代码中的错误。然而,即使在这种情况下,您也必须适当地设置预期结果和允许的错误容差。
AlmostEquals
代码似乎对容错性进行了硬编码。

同意,除了像AlmostEquals这样的函数是坏的。只有当您为通用浮点定义它们时,它们才是坏的;相反,它们应该为特定于程序的数字类型定义。如果您有剂量、坐标、振幅等类,则每个类都是必需的为float创建一个包装器,每个包装器都有自己适用的动态范围和公差,然后为这些类中的每个类定义一个近似比较,并具有适当的类型特定公差。这将防止在代码的不同部分对剂量变量进行不一致的比较。@Michael:公差不是由类型决定的。例如,见第5节,Kahan的J-M.Muller递推。基本上,无论类型如何,该递推的计算收敛到100。数学上正确的极限为5。无论精度如何,误差为95。要计算公差,您必须具有完整的上下文,包括先前计算和数据的知识。(William Kahan是我们拥有IEEE 754的原因。这篇论文值得一读。)我想这取决于你想做什么。对我来说,每种数字类型的预期公差是非常清楚的,但也许这是因为每种类型所做的计算在类型内相当一致。:)对于Coord,这将是计算几何算法;对于Dose,这将是具有截断支持的内核的卷积等。我们知道我们对每种类型所做的操作的大致精度,因此可以定义每种类型的公差。替代方法-由于不一致的比较而定义不清的假设-更糟糕:它们可能导致可怕的bug。我应该更清楚导致bug的假设。假设你有类似if(比较(