c++ 如何在Catch框架中使用浮点公差?

jtoj6r0c  于 2023-01-28  发布在  其他
关注(0)|答案(4)|浏览(139)

我使用的是Catch测试框架。
introductory blog post中,作者提到了以下功能:

  • 以易于使用的方式支持浮点公差

我找不到任何文档来说明如何做这件事。在Catch中是如何做的?

pgky5nke

pgky5nke1#

很简单,有一个名为Approx的类,可以让你以一种可读性很强的方式来完成这个测试:

#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));
}

可以使用Approx对象的成员函数epsilon()scale()来更改容差,如下所示:Approx(a).epsilon(e) .

vddsk6oq

vddsk6oq2#

公差是可定制的since Apr 2011Approx有两个成员函数用于此:epsilon()scale()。例如:

REQUIRE(a == Approx(b).epsilon(my_eps));

容差为ε ×(scale+max(|a|,|B|)),其中scale默认为1,因此该操作将通过:

REQUIRE((2+2) == Approx(5).epsilon(0.17));
nuypyhwy

nuypyhwy3#

我知道这是一个老问题,但我只是偶然发现了同样的问题,并找到了一个简单的解决方案。在定义Approx类的Catch.hpp头文件中(编写时的第2045行),只需添加以下构造函数:

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 )
    {}

现在您可以执行以下操作:

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)); 
}
cyej8jka

cyej8jka4#

值得注意的是Approx现在被认为是过时的[source]:
Approx的缺点是它有几个问题,我们无法在不破坏向后兼容性的情况下修复这些问题。因为Catch2还提供了实现不同浮点比较方法的完整匹配器集,所以Approx保持原样,被认为是过时的,不应该在新代码中使用。
从2.10版开始,应该改用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()));
    }

相关问题