如何有效地比较包含双精度的std :: tuple是否相等

时间:2012-11-28 11:01:27

标签: c++ optimization c++11 floating-point

我想比较两个包含尽可能高效的双元组的元组。

由于浮点精度,使用预定义的运算符==(...)无法做到这一点,最好的方法是什么?我是否真的需要遍历所有元组元素或者是否有一些我可以使用的模板魔法,这可能允许编译器调用一些SIMD优化?

2 个答案:

答案 0 :(得分:6)

比较浮点值的平等是一种误解。在任何没有严重破坏的实现中,当且仅当比较的值相等时,比较等式的浮点值才返回true。

任何实际错误都在计算的早期。必须控制和表征这些错误。如果没有对错误进行描述,就无法就适合您的目的执行哪些操作提出任何建议。

如果您的值已经不精确地计算,以便它们可能包含一些错误,并且您希望接受实际上不相等的相等值,那么您必须声明(a)接受相等的标准,并且(b) )拒绝平等的标准。当陈述这些标准时,人们可能会给出关于实施满足两个标准的测试的建议。请注意,(b)和(a)一样重要,因为您通常不希望接受实际上不相等的相等值。由于计算中存在错误,因此某些决策将是错误的,您必须确定标准(a)和(b),以便您的应用程序可以接受错误的决策。重要的是(a)和(b)不重叠,否则将会出现无法接受决定的情况。

在您的情况下,除了从文件中读取数据之外,您没有声明任何错误来源。如果文件中的数据是由良好的软件写入的浮点计算的结果(正确地将浮点值转换为具有足够精度的十进制数字),并且您使用良好的软件(正确地将十进制数字转换为浮点数)来读取它点值),这次数据往返没有错误,你应该只测试没有装饰的相等。

答案 1 :(得分:0)

好的,基于对元组的运算符==()的STL实现,我创建了这个,这允许我对某些类型使用我想要的任何比较函数:

template<class T>
bool
tupleEqualHelper (const T& lhs, const T& rhs)
{
  return lhs == rhs;
}

template<>
bool tupleEqualHelper<double> (const double& lhs, const double& rhs)
{
 return return (fabs (lhs - rhs) < (std::numeric_limits<double>::epsilon () * 100));
}

template<counter_t i, counter_t j, class T>
struct compareHelper;

template<counter_t i, counter_t j, class T>
struct compareHelper
{
  static bool tupleEqual (const T& lhs, const T & rhs)
  {
    return tupleEqualHelper (std::get<i > (lhs), std::get<i > (rhs)) &&
            compareHelper < i + 1, j, T>::tupleEqual (lhs, rhs);
  }
};

template<counter_t i, class T>
struct compareHelper<i, i, T>
{
  static bool tupleEqual (const T&, const T&)
  {
    return true;
  }
};

template<class ... TTypes>
bool
compareTuple (const std::tuple<TTypes...>& lhs, const std::tuple<TTypes...>& rhs)
{
  typedef std::tuple < TTypes...> Tp;

  return compareHelper < 0, std::tuple_size<Tp>::value, Tp>::tupleEqual (lhs, rhs);
}