我正在使用UnitTest编写一个Catch2。
我想检查两个向量是否相等。它们使用gmplib看起来如下所示:
std::vector<mpf_class> result由于我“伪造”了expected_result向量,在测试失败后我得到了以下消息:
unittests/test.cpp:01: FAILED:
REQUIRE( actual_result == expected_result )
with expansion:
{ 0.5, 0.166667, 0.166667, 0.166667 }
==
{ 0.5, 0.166667, 0.166667, 0.166667 }所以我在寻找一个函数,它可以为我做一个近似。
我只是没能找到一个适合我的解决方案。
我找到了一些比较函数,但它们不适用于我的项目。
编辑:“最小的、可复制的示例就是:
TEST_CASE("DemoTest") {
// simplified:
mpf_class a = 1;
mpf_class b = 6;
mpf_class actual_result = a / b;
mpf_class expected_result= 0.16666666667;
REQUIRE(actual_result == expected_result);
}

与我的实际应用程序“唯一”的区别是,结果存储在向量中。但因为我只是“假装”的结果,说它是"0.1666666667“,它可能不适合==了。所以我需要一个函数来进行近似,并比较epsilon = +-0.001这样的范围。
编辑:在实现了这个解决方案之后,@arc建议它运行得很好,直到我有了一些不完整的“偶数”值。
因此,下面的值失败了:
actual 0.16666666666666666666700000000000000000000000000000
expected 0.16666666666666665741500000000000000000000000000000尽管我的“预期”值如下所示:
mpf_class expected = 0.16666666666666666666700000000000000000000000000000回到我最初的问题,如果有一种方法,我可以比较这个数字的近似和一个类似-0.0001的epsilon,或者什么是解决这个问题的最好方法?
发布于 2022-01-07 02:41:49
首先,我们需要看到一些最小的,可复制的例子来确定正在发生的事情。例如,您可以从test.cpp中减少一些代码,直到只剩下几行代码,但问题仍然存在。此外,请提供编译和运行说明。通常,对你的目标做一点解释也会有所帮助。由于Catch2可以在GitHub上使用,所以不需要提供它。
在没有看到代码的情况下,我能猜到的最好的情况是,您的代码试图使用mpf_t操作符比较mpf_class中的==类型,我担心它没有超载(参见这里)。您应该将mpf_t与cmp函数进行比较,因为C类型mpf_t实际上是一个包含指向实际意义和分支的指针的结构。检查GMP的tests/cxx/目录中的一些使用示例(如这里)。
我注意到您正在使用GNU 4.1版本,这是非常老的版本,如果可能的话,您可能希望使用6.2.1最新版本。此外,对于使用浮标,建议您使用GNU MPFR库而不是GMP。
编辑:我还没有设法运行Catch2,但是您的代码的问题是expected_result实际上并不等于actual_result。在GMP中,mpf_t变量具有64位意义和精度(在64位机器上),因此除法a / b实际上生成了一个二进制文件,该二进制文件输出0.16666666666666667(这是数字1之后的19个6位)。尝试用gmp_printf("%.50Ff\n", actual_result);打印结果,因为标准的cout输出将只给出6位数的值: 0.166667。
但是问题是您不能像expected_result = 0.166666666666666666667那样分配这个值,因为在C/C++中,数值常量被解析为double,因此您必须使用字符串重载属性来获得更高的精度。
但是,您也不能轻松地(或者,通常来说,合理地)创建一个小数字符串,它将正确地转换为a / b给出的完全相同的二进制,因为十进制到浮点转换具有微妙性,例如这里和这里。
所以,这完全取决于你的应用程序和你想要做的数值验证的类型。如果您知道您的十进制验证值对某些已知的精度是正确的,并且如果您将mpf_t变量设置为抵挡精度(例如使用mpf_set_prec),那么您可以使用容差比较,如下所示。
在C++ (没有Catch2)中,它的工作方式如下:
#include <iostream>
#include <gmpxx.h>
using namespace std;
int main (void)
{
mpf_class a = 1;
mpf_class b = 6;
mpf_class actual = a / b;
mpf_class expected;
mpf_class tol;
expected = "0.166666666666666666666666666666667";
tol = "1e-30";
cout << "actual " << actual << "\n";
cout << "expected " << expected << "\n";
gmp_printf("actual %.50Ff\n", actual);
gmp_printf("expected %.50Ff\n", expected);
gmp_printf("tol %.50Ff\n", tol);
mpf_class diff = expected - actual;
gmp_printf("diff %.50Ff\n", diff);
if (abs(actual - expected) < tol)
cout << "ok\n";
else
cout << "nop\n";
return 0;
}并使用-lgmpxx -lgmp选项编译。
它产生的输出:
actual 0.166667
expected 0.166667
actual 0.16666666666666666666700000000000000000000000000000
expected 0.16666666666666666666700000000000000000000000000000
tol 0.00000000000000000000000000000100000000000000000000
diff 0.00000000000000000000000000000000033333529249058470
ok如果我对Catch2有很好的理解,那么如果您用字符串分配expected_result,然后与REQUIRE(abs(actual - expected) < tol)进行比较,那就没问题了。
https://stackoverflow.com/questions/70611257
复制相似问题