gpt4 book ai didi

c++ - Boost.Test 自定义类型使用装饰器 boost::unit_test::tolerance

转载 作者:行者123 更新时间:2023-11-30 05:31:18 25 4
gpt4 key购买 nike

我经常使用 Boost.Test 来测试数值。我经常需要比较数学对象的值。下面是一个玩具示例,展示了我如何进行大量测试。

#define BOOST_TEST_MODULE VektorTest
#include <boost/test/included/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>

struct Vector {
Vector(double x, double y, double z) : x(x), y(y), z(z) {}
double x;
double y;
double z;
};

BOOST_AUTO_TEST_CASE(Rotations, * boost::unit_test::tolerance(1.0e-2)) {
Vector vector1(1.5,3.,7.4);
Vector vector2(1.51, 3.01, 7.41);

// The following can get really annoying and is error prone.
BOOST_TEST(vector1.x==vector2.x);
BOOST_TEST(vector1.y==vector2.y);
BOOST_TEST(vector1.z==vector2.z);

// This should be the expected usage, but only if the tolerance is considered.
// BOOST_TEST(vector1==vector2); // Will not compile!
}

我可以教 Boost.Test 识别考虑 boost::unit_test::tolerance 的自定义类型吗?装潢师?

单纯的一对一内容比较x,y,zVector object 将不是可行的解决方案。

#define BOOST_TEST_MODULE VektorTest #包括 #包括

结构 vector { vector (双 x、双 y、双 z):x(x)、y(y)、z(z){}

double x;
double y;
double z;

};

编辑

在仔细研究了 Boost.Test 的文档之后,我发现了有趣的函数 per_element() , 这允许比较序列中包含的值。这个功能已经是一个很大的好处,因为它考虑了 tolerance装饰器,如下所示。一个std::vector<T>满足序列接口(interface),可以很好地在这个框架内使用。

Boost.Test 文档说,一个序列应该实现 size()begin()函数,以及字段 const_iteratorvalue_type .对于我来说,这不是一个可行的解决方案,因为我无法更改数学类的接口(interface)。更重要的是,我无法扩展下面的玩具示例来满足这个接口(interface)。

 #define BOOST_TEST_MODULE VektorTest
#include <boost/test/included/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>

struct Vector {
Vector(double x, double y, double z) : x(x), y(y), z(z) {}

double x;
double y;
double z;

};

BOOST_AUTO_TEST_CASE(VectorTest, * boost::unit_test::tolerance(1.0e-4)) {
{
std::vector<double> vector1;
vector1.push_back(1.5);
vector1.push_back(3.);
vector1.push_back(7.4);

std::vector<double> vector2;
vector2.push_back(1.51);
vector2.push_back(3.01);
vector2.push_back(7.41);
BOOST_TEST(vector1==vector2, boost::test_tools::per_element());
}

{
Vector vector1(1.5,3.,7.4);
Vector vector2(1.51, 3.01, 7.41);

//BOOST_TEST(vector1==vector2, boost::test_tools::per_element()); // Will not compile!!!
}
}

最佳答案

我不确定是否完全理解您的问题,但也许 BOOST_TEST_SPECIALIZED_COLLECTION_COMPARE (参见 here )是您问题的答案。

编辑:良性复杂的方式

如果你想考虑你的 Vektor作为应执行基于公差的比较的类型,那么您可能会查看 here在文档中

你需要的是:

  • 使您的类与基于公差的比较兼容(需要 EqualityComparableLessThanComparable )。所有比较(参见 herethere )操作都涉及要计算的两个值之间的差异,因此您需要您的类来实现 LessThanComparable ,否定 - 绝对值 - 和从单一值构造 - 原点所需 - 。 boost.operators在这里可能会有很好的帮助。
  • 通过声明 tolerance_based 的特化来通知 boost.test 您的类与基于公差的操作兼容为你的类(class)

在您的情况下,您想要实现的公差区域位于特定位置周围的 3D 立方体内。给定公差\epsilon,

  • 落在这个立方体中的 vector “足够接近”wrt。\epsilon
  • 落在立方体之外的 vector 被认为“足够远”

所有这些操作都是由 close_at_tolerance 执行的.

因为你想执行每个轴的公差,你可以实现

  • operator-作为每个轴的差异
  • operator- (一元否定)作为每个轴的否定
  • operator<作为每个轴的比较
  • operator/作为每个轴的划分

operator<operator- (一元)用于计算绝对值。

但是,这不会像预期的那样工作 std::maxstd::min也应该实现(参见 here )。在您的情况下,他们应该提供 maxmin每个轴。目前

  • 最简单的方法是实现 close_at_tolerance 的特化(参见 here)。
  • 或实现std::minstd::max并专注于boost::math::fpc::fpc_detail::fpt_abs (私有(private) API)用于计算绝对值。

归根结底,这只是比较的问题。公差、差异和绝对值计算。

如果你拿走

|v1 - v2| = (|a1-a2|, |b1-b2|, |c1-c2|)
|v1 - v2|/|v1| = (|a1-a2|/|a1|, |b1-b2|/|b1|, |c1-c2|/|c1|) // same for v2
max(|v1 - v2|/|v1|, |v1 - v2|/|v2|) = (max(|a1-a2|/|a1|, |a1-a2|/|a2|),
max(|b1-b2|/|b1|, |b1-b2|/|b2|),
... )

执行测试需要的是:

|v1 - v2|/|v1| < eps. && |v1 - v2|/|v2| < eps.
=> max(|v1 - v2|/|v1|, |v1 - v2|/|v2|) < eps.
=> max(|v1 - v2|/|v1|, |v1 - v2|/|v2|) < vektor(eps., eps., eps.)
=> max(|a1-a2|/|a1|, |a1-a2|/|a2|) < eps.
&& max(|b1-b2|/|b1|, |b1-b2|/|b2|) < eps. ...

并且它与每轴的最大值、除法和比较一致。

关于c++ - Boost.Test 自定义类型使用装饰器 boost::unit_test::tolerance,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35623727/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com