用户@skrebbel在this上发布帖子时表示,谷歌测试框架在比较浮点数和双精度数方面做得很好,速度也很快。因此,我编写了以下代码来检查代码的有效性,显然,我似乎在这里遗漏了一些东西,因为我希望输入几乎等于的部分这是我的代码
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 ?
}
如有任何建议,我们将不胜感激。
发布于 2013-09-07 05:37:15
您的left
和right
不是“几乎相等”,因为它们的距离太远,比AlmostEquals
的默认容差更远。您链接到的问题的其中一个答案中的代码显示公差为4 ULP,但您的数字之间相距14 ULP (使用IEEE 754 32位二进制和正确舍入软件)。( ULP是浮点值的最小增量。它对于小幅度的浮点数来说是小的,而对于大数来说是大的,因此它大约与数字的大小相关。)
在不了解正在比较的值中可能存在的错误以及正在执行的比较的情况下,永远不应执行任何浮点比较。
人们经常错误地认为您不能测试浮点值是否相等。这是假的;执行a == b
是一个完美的操作。当且仅当a
等于b
(即,a
和b
是具有完全相同值的数字)时,它才返回true。实际问题是,在输入错误的情况下,他们试图计算一个正确的函数。==
是一个函数:它接受两个输入并返回一个值。显然,如果您给任何函数错误的输入,它可能会返回错误的结果。所以这里的问题不是浮点比较,而是不正确的输入。在输入错误的情况下,通常无法正确计算和、乘积、平方根、对数或任何其他函数。因此,在使用浮点时,您必须设计一种算法来处理近似值(或者,在特殊情况下,要非常小心,以确保不会引入错误)。
通常,人们试图通过接受略有不同的相等数字来解决浮点值中的错误。这减少了假阴性(由于先前的计算错误而导致的不平等的迹象),但代价是增加了假阳性(由于接受不严格而导致的相等的迹象)。这种从一种错误到另一种错误的交换是否可接受取决于应用程序。没有通用的解决方案,这就是为什么像AlmostEquals
这样的函数通常是不好的。
浮点值中的错误是前面的操作和值的结果。根据环境的不同,这些误差的范围从零到无穷大。因此,永远不能简单地接受AlmostEquals
等函数的默认容差。相反,人们应该计算公差,它特定于他们的应用程序、需求和计算,并使用计算出的公差(或者根本不使用比较)。
另一个问题是,诸如AlmostEquals
之类的函数通常是使用相对于要比较的值指定的容差编写的。但是,这些值中的误差可能已经受到大小不同的中间值的影响,因此最终的误差可能是所比较的值中不存在的数据的函数。
在测试其他代码的代码中,“近似”浮点比较可能是可接受的,因为大多数错误可能会导致大错误,因此对相等的松散接受将允许良好的代码继续,但将在大多数糟糕的代码中报告错误。但是,即使在这种情况下,也必须适当地设置预期结果和允许的误差容限。AlmostEquals
代码似乎对容错进行了硬编码。
https://stackoverflow.com/questions/18666691
复制相似问题