使用 Catch2 以全精度打印浮点值
Printing floating-point values with full precision with Catch2
我有一些使用 catch2 的测试代码,它确实检查某些计算 returns 是否为浮点空值。
CHECK( someFunc() == 0. );
问题是当测试因为非常小的非空值(比如 1.234E-16)而失败时,这些值是用 "default" 打印出来的,我看到:
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::cout
中流式传输 std::scientific
,但显然 Catch 使用了另一种打印方法。
有什么想法吗?
旁注:实际上,我使用提供的 Approx
class 但这与我的问题无关
编辑:这里的问题是不是比较本身(我知道浮点值的所有坏处), 只有关于我如何告诉 Catch 打印处理的值。
更新:你can now specify precision in Catch2。以下适用于旧版本的 Catch2。
看起来精度是在 Catch2 本身中硬编码的:
std::string StringMaker<float>::convert(float value) {
return fpToString(value, 5) + 'f';
}
std::string StringMaker<double>::convert(double value) {
return fpToString(value, 10);
}
有两个选项可以解决这个问题:
选项 1:修改 Catch2
如果你修改它,你可以让它显示你想要的(注意:<limits>
已经包含在 catch 中,所以我将使用 std::numeric_limits
):
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);
}
可以采用更复杂的方法将其作为用户可以设置的参数,而不是将其硬编码为不同的半任意值,但这只是一个问答,而不是拉取请求。 ;-)
方案二:自己记录,精度更高
如果您在 REQUIRE()
调用之前添加 INFO( FullPrecision(d) );
,您将获得完全精确的打印,但只有在测试用例失败时才会如此。 (参见下面 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 );
}
打印:
prog.cc:20: FAILED:
REQUIRE( 0.0 == d )
with expansion:
0.0 == 0.00000000000000022
with message:
2.2204460492503131e-16
修改 Catch2 导致扩展 0.0 == 0.00000000000000022
,添加 INFO()
导致消息 2.2204460492503131e-16
。
在 Wandbox.
上观看直播
我有一些使用 catch2 的测试代码,它确实检查某些计算 returns 是否为浮点空值。
CHECK( someFunc() == 0. );
问题是当测试因为非常小的非空值(比如 1.234E-16)而失败时,这些值是用 "default" 打印出来的,我看到:
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::cout
中流式传输 std::scientific
,但显然 Catch 使用了另一种打印方法。
有什么想法吗?
旁注:实际上,我使用提供的 Approx
class 但这与我的问题无关
编辑:这里的问题是不是比较本身(我知道浮点值的所有坏处), 只有关于我如何告诉 Catch 打印处理的值。
更新:你can now specify precision in Catch2。以下适用于旧版本的 Catch2。
看起来精度是在 Catch2 本身中硬编码的:
std::string StringMaker<float>::convert(float value) {
return fpToString(value, 5) + 'f';
}
std::string StringMaker<double>::convert(double value) {
return fpToString(value, 10);
}
有两个选项可以解决这个问题:
选项 1:修改 Catch2
如果你修改它,你可以让它显示你想要的(注意:<limits>
已经包含在 catch 中,所以我将使用 std::numeric_limits
):
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);
}
可以采用更复杂的方法将其作为用户可以设置的参数,而不是将其硬编码为不同的半任意值,但这只是一个问答,而不是拉取请求。 ;-)
方案二:自己记录,精度更高
如果您在 REQUIRE()
调用之前添加 INFO( FullPrecision(d) );
,您将获得完全精确的打印,但只有在测试用例失败时才会如此。 (参见下面 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 );
}
打印:
prog.cc:20: FAILED:
REQUIRE( 0.0 == d )
with expansion:
0.0 == 0.00000000000000022
with message:
2.2204460492503131e-16
修改 Catch2 导致扩展 0.0 == 0.00000000000000022
,添加 INFO()
导致消息 2.2204460492503131e-16
。
在 Wandbox.
上观看直播