我有一些使用qazxsw poi的测试代码,它会检查某些计算是否返回浮点空值。
catch2
问题是,当测试因非常小的非空值(例如1.234E-16)而失败时,值将以“默认”打印打印,我看到:
CHECK( someFunc() == 0. );
这几乎没用。我想看到的是:
my_test.cpp:351: FAILED:
CHECK( someFunc() == 0.0 )
with expansion:
0.0 == 0.0
我在测试前尝试在my_test.cpp:351: FAILED:
CHECK( someFunc() == 0.0 )
with expansion:
1.234E-16 == 0.0
中流式传输std::scientific
,但显然使用其他打印方法Catch。
任何的想法 ?
旁注:实际上,我使用提供的std::cout
类,但这与我的问题无关
编辑:这里的问题不是关于比较本身(我知道浮点值的所有邪恶的东西),它只是关于如何告诉Catch打印处理值。
更新:你Approx
can now。以下适用于旧版本的Catch2。
看起来精度在Catch2本身内是硬编码的:
specify precision in Catch2
有两种方法可以解决这个问题:
选项1:修改Catch2
如果你修改它,你可以让它显示你想要的东西(注意:std::string StringMaker<float>::convert(float value) {
return fpToString(value, 5) + 'f';
}
std::string StringMaker<double>::convert(double value) {
return fpToString(value, 10);
}
已经包含在catch中,所以我将使用<limits>
):
std::numeric_limits
可以采用更复杂的方法将此作为用户可以设置的参数而不是将其硬编码为不同的半任意值,但这只是问答,而不是拉取请求。 ;-)
选项2:以更高的精度自行记录
如果你在std::string StringMaker<float>::convert(float value) {
return fpToString(value, std::numeric_limits<float>::max_digits10) + 'f';
}
std::string StringMaker<double>::convert(double value) {
return fpToString(value, std::numeric_limits<double>::max_digits10);
}
调用之前添加INFO( FullPrecision(d) );
,你将得到一个完整的精度打印,但只有当测试用例失败时。 (见下面REQUIRE()
的定义。)
这些变化都在这里展示:
FullPrecision()
打印:
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
#include "catch.hpp"
#include <limits>
#include <sstream>
#include <iomanip>
double GetDouble() { return std::numeric_limits<double>::epsilon(); }
std::string FullPrecision( double d )
{
auto s = std::ostringstream{};
s << std::setprecision( std::numeric_limits<double>::max_digits10 ) << d;
return s.str();
}
TEST_CASE( "Double, double, toil and trouble", "[double]" )
{
const auto d = GetDouble();
INFO( FullPrecision(d) );
REQUIRE( 0.0 == d );
}
修改Catch2导致扩展prog.cc:20: FAILED:
REQUIRE( 0.0 == d )
with expansion:
0.0 == 0.00000000000000022
with message:
2.2204460492503131e-16
,并添加0.0 == 0.00000000000000022
导致消息INFO()
。
在2.2204460492503131e-16
上看到它。