比较浮点数 - 谷歌测试框架

Comparing Floating Point Nos - Google Test Framework

本文关键字:测试 框架 谷歌 浮点数 比较      更新时间:2023-10-16

在SO上阅读这篇文章时,用户@skrebbel表示谷歌测试框架在比较浮点数和双精度数方面做得很好。所以我写了以下代码来检查代码的有效性,显然我在这里似乎缺少一些东西,因为我期望在这里输入几乎等于的部分,这是我的代码

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 ?
}

任何建议将不胜感激。

您可以使用

ASSERT_NEAR(val1, val2, abs_error); 

您可以在其中给出可接受的 - 您选择的一个,例如,比如说 0.0000001 - 差异作为abs_error,如果默认的太小,请参阅此处 https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#floating-point-comparison

您的leftright不是"几乎相等"的,因为它们相距太远,比默认容差AlmostEquals更远。您链接到的问题之一答案中的代码显示容差为 4 ULP,但您的数字相距 14 ULP(使用 IEEE 754 32 位二进制和正确舍入软件)。(ULP 是浮点值的最小增量。对于小量级的浮点数,它很小,对于大数来说很大,所以它大约相对于数字的量级。

在不知道要比较的值中可能存在哪些错误以及正在执行的比较的情况下,切勿执行任何浮点比较。

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

通常,人们试图通过接受略有不同的相等数字来解决浮点值中的错误。这减少了假阴性(由于先前计算错误而导致的不平等迹象),但代价是增加了误报(由宽松接受引起的平等迹象)。这种将一种错误交换为另一种错误是否可以接受取决于应用程序。没有通用的解决方案,这就是为什么像AlmostEquals这样的功能通常很糟糕的原因。

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

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

在测试其他代码的代码中,"近似"浮点比较可能是可以接受的,因为大多数错误可能会导致大错误,因此对平等的宽松接受将允许好代码继续,但会在大多数坏代码中报告错误。但是,即使在这种情况下,也必须相应地设置预期结果和允许的容错能力。AlmostEquals代码似乎对容错进行了硬编码。

(不确定这是否 100% 适用于原始问题,但这是我偶然发现它时的目的)

还有ASSERT_FLOAT_EQEXPECT_FLOAT_EQ(或双精度的相应版本),如果您不想自己担心可容忍的错误,可以使用它们。

文档:https://github.com/google/googletest/blob/master/docs/reference/assertions.md#floating-point-comparison-floating-point