c++ - 如何比较catch2中的浮点数
问题描述
我正在使用 Catch v2.13.1
比较浮点值的正确方法是什么。我认为下面会失败,但都通过了。
REQUIRE(1147332687.7189338 == Approx(1147332688.4281545).margin(0.0001));
REQUIRE(1147332687.7189338 == Approx(1147332688.4281545));
然而,这如预期的那样失败
REQUIRE(abs(1147332687.7189338 - 1147332688.4281545) <= Approx(0).margin(0.0001));
我不明白为什么前两个语句不起作用
解决方案
在发布的示例中有几件事需要考虑。
REQUIRE(1147332687.7189338 == Approx(1147332688.4281545));
这会“出乎意料地”过去。原因可以在文档中找到(断言 - 浮点比较)。
Approx
使用应涵盖大多数简单情况的默认值构造。对于更复杂的情况,Approx 提供了 3 个自定义点:
- epsilon - epsilon 用于设置结果
Approx
在被拒绝之前与 ' 值不同的系数。默认设置为std::numeric_limits<float>::epsilon()*100
.- [...]
在发布的示例中,这两个数字的系数相差接近 6.2e-10,而默认值(给定 32 位浮点数)接近 1.2e-5。
以下测试不会通过。
CHECK( a == Approx(b).epsilon(1e-12) );
其他测试涉及margin
,在文档中描述为
- 边距- 边距用于设置结果在被拒绝之前可能与 Approx 的值不同的绝对值。默认设置为 0.0。
但是,可以在issue#1507中找到警告。
这是因为 Approx 类中 epsilon 的默认值以及 Approx::equalityComparisonImpl 如果值在边距或epsilon 值的范围内将通过的事实。
所以,这个测试不会通过:
CHECK( a == Approx(b).margin(0.0001).epsilon(1e-12) );
请注意,这个“问题”似乎被标记为已解决——不是错误:
所以,我不认为这是一个错误。
这样做的原因是很难(嗯,不可能)确定用户的意图,因此最好假设用户已经正确设置了两个检查——毕竟,如果用户不想要一个亲戚相比之下,他们总是可以将 epsilon 设置为零。事实上,我认为同时使用容差并采用最宽容的容差是实现 Approx Matcher ( #1499 ) 之类的最佳选择。