【问题标题】:How to efficiently compare std::tuple containing doubles for equality [closed]如何有效地比较包含双精度的 std::tuple 是否相等[关闭]
【发布时间】:2012-11-29 21:24:48
【问题描述】:

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

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

【问题讨论】:

  • 尽可能高效地涉及某种形式的运算符 ==。您似乎还有其他要求(“因为浮点精度”),但不知何故认为您的唯一要求是效率。
  • 你可能应该尝试正确解决这个问题,因为这对双打来说不是一件容易的事,在你分析它并尝试让它更有效(如果可能的话)跨度>
  • 效率只是一个问题。另一个是数据集是从文件中读取的,这就是为什么 operator==() 几乎不可能的原因。
  • 嗯,为什么从文件中读取意味着无法测试相等性?
  • 有些值是只读的,有些是可以计算的,有些是用户自己输入的。所以我想我的问题应该是“如何对元组中的某些类型使用自定义相等运算符”

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


【解决方案1】:

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

任何实际错误都存在于您的计算中。这些错误必须得到控制和表征。如果不对错误进行表征,就不可能就执行哪些操作以适合您的目的提出任何建议。

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

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

【讨论】:

    【解决方案2】:

    好的,基于我为元组创建的 operator== () 的 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);
    }
    

    【讨论】:

      猜你喜欢
      • 2013-08-16
      • 2015-03-13
      • 2022-10-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多