【问题标题】:Search for nearest value in an array of doubles in C++?在 C++ 中的双精度数组中搜索最接近的值?
【发布时间】:2010-10-16 11:01:00
【问题描述】:

我在 C++ 中有一个双精度值的排序数组。是否有一个 STL 函数可以将数组中 最近 值的 index 返回到给定的 double 值?

例如,给定以下数组

double myarray[5] = { 1.0, 1.2, 1.4. 1.5, 1.9 };

函数调用

search(myarray, 1.6);

应该返回 3,即最接近 1.6 的元素的索引,而不是 -1(或其他一些标志值),表示未找到值 1.6。

【问题讨论】:

  • 几乎是this post的副本。
  • 我们可以将“std::min_element”与仿函数一起使用,看看我的例子。

标签: c++ search stl


【解决方案1】:

也许std::lower_bound std::upper_bound 会帮助你。

【讨论】:

    【解决方案2】:

    这是使用std::lower_bound 的通用解决方案:

    template <typename BidirectionalIterator, typename T>
    BidirectionalIterator getClosest(BidirectionalIterator first, 
                                     BidirectionalIterator last, 
                                     const T & value)
    {
        BidirectionalIterator before = std::lower_bound(first, last, value);
    
        if (before == first) return first;
        if (before == last)  return --last; // iterator must be bidirectional
    
        BidirectionalIterator after = before;
        --before;
    
        return (*after - value) < (value - *before) ? after : before;
    }
    

    您会注意到我使用了双向迭代器,这意味着该函数只能与可以递增和递减的迭代器一起使用。更好的实现只会强加输入迭代器的概念,但对于这个问题,这应该足够了。

    既然你想要索引而不是迭代器,你可以写一个小辅助函数:

    template <typename BidirectionalIterator, typename T>
    std::size_t getClosestIndex(BidirectionalIterator first, 
                                BidirectionalIterator last, 
                                const T & value)
    {
        return std::distance(first, getClosest(first, last, value));
    }
    

    现在你会得到这样的代码:

    const int ARRAY_LENGTH = 5;
    double myarray[ARRAY_LENGTH] = { 1.0, 1.2, 1.4. 1.5, 1.9 };
    
    int getPositionOfLevel(double level)
    {
        return getClosestIndex(myarray, myarray + ARRAY_LENGTH, level);
    }
    

    给出以下结果:

    level | index
     0.1  |  0
     1.4  |  2
     1.6  |  3
     1.8  |  4
     2.0  |  4
    

    【讨论】:

    • +1 - 我没有使用你的代码,但它帮助我找到了自己的错误。
    【解决方案3】:

    数组是否保证按升序排列?如果有,请给std::lower_bound 看看。

    【讨论】:

    • 是的,保证是升序。 std::lower_bound 确实有效,谢谢。
    【解决方案4】:

    我认为我的示例完全符合您的要求:

    (我使用 std::min_element 和仿函数)

    #include <algorithm>
    #include <cmath>
    
    const int ARRAY_LENGTH = 5;
    double myarray[ARRAY_LENGTH] = { 1.0, 1.2, 1.4, 1.5, 1.9 };
    
    struct CompareDistanceFromLevel
    {
        CompareDistanceFromLevel(double cLevel) : level(cLevel) {}
    
        bool operator()(double lhs, double rhs)
        {
            return std::abs(level - lhs) < std::abs(level - rhs);
        }
    
    private:
        double level;
    };
    
    size_t getPositionOfLevel(double level)
    {
        double *result;
        result = std::min_element(myarray, myarray+ARRAY_LENGTH, CompareDistanceFromLevel(level));
        return (result-myarray); // returns the index
    }
    

    【讨论】:

      【解决方案5】:
      #include "stdafx.h"
      #include <limits>
      
      using namespace std;
      
      static const int array_len = 5;
      double myarray[array_len] = { 1.0, 1.2, 1.4, 1.5, 1.9 };
      
      int approx_search(const double val)
      {
          double min_val = numeric_limits<double>::max();
          int index = 0;
      
          for(int i=0;i<array_len;++i)
          {
              double diff = abs(myarray[i] - val);
              if(diff<min_val)
              {
                  min_val = diff;
                  index = i;
              }
          }
          return index;
      }
      int _tmain(int argc, _TCHAR* argv[])
      {
          printf("approximate %d\n",approx_search(1.6));
          printf("approximate %d\n",approx_search(1.7996));
          printf("approximate %d\n",approx_search(1.4996));
          printf("approximate %d\n",approx_search(0.0002));
      
          return 0;
       }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-19
        • 2017-02-23
        • 2019-07-13
        相关资源
        最近更新 更多