I'm using the Catch test framework.
In the introductory blog post the author mentions the following feature:
开发者_运维知识库
- Floating point tolerances supported in an easy to use way
I couldn't find any documentation on how to do this. How is this done in Catch?
It's simple. There is a class called Approx
that lets you do this test in a very readable manner:
#include <limits>
TEST_CASE("demo/approx", "Approx demo") {
double a = 1.0;
double b = a + std::numeric_limits<double>::epsilon();
REQUIRE_FALSE(b == a);
REQUIRE(b == Approx(a));
}
The tolerance can be changed by using the member functions epsilon()
and scale()
of the Approx
object, like so: Approx(a).epsilon(e)
.
The tolerance is has been customizable since Apr 2011. Approx
has two member functions for this: epsilon()
and scale()
. For example:
REQUIRE(a == Approx(b).epsilon(my_eps));
The tolerance is ε × (scale+max(|a|, |b|)), where scale defaults to 1, so this will pass:
REQUIRE((2+2) == Approx(5).epsilon(0.17));
I know this is an old question, but I just stumbled upon the same problem and found a simple solution. In the Catch.hpp header file where the Approx class is defined (line 2045 at the time of writing), just add the following constructor:
class Approx {
public:
explicit Approx( double value )
: m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
m_scale( 1.0 ),
m_value( value )
{}
explicit Approx( double value, double epsilon ) // <- New constructor
: m_epsilon( epsilon ),
m_scale( 1.0 ),
m_value( value )
{}
Now you can do this:
TEST_CASE("demo/approx", "Approx demo") {
double myTol = 0.1;
double a = 1.0;
double b = a + myTol;
REQUIRE_FALSE(a == b);
REQUIRE(a == Approx(b, myTol));
}
It is important to note that Approx
is now considered deprecated [source]:
The downside to Approx is that it has a couple of issues that we cannot fix without breaking backwards compatibility. Because Catch2 also provides complete set of matchers that implement different floating point comparison methods, Approx is left as-is, is considered deprecated, and should not be used in new code.
As of version 2.10, one should switch to using Matchers
.
#include <limits>
#include <catch2/matchers/catch_matchers_floating_point.hpp>
TEST_CASE("demo/matchers", "Matchers demo") {
double a = 1.0;
double b = a + std::numeric_limits<double>::epsilon();
REQUIRE_FALSE(b == a);
REQUIRE_THAT(b, Catch::Matchers::WithinRel(a, std::numeric_limits<double>::epsilon()));
}
精彩评论