在C++中查找最接近的双精度数组值?

7

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

例如,给定以下数组:

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

函数调用
search(myarray, 1.6);

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

基本上是这篇帖子的副本。 - mwigdahl
我们可以使用带有函数对象的“std::min_element”,看看我的例子。 - Rexxar
5个回答

12

也许你可以尝试使用 std::lower_boundstd::upper_bound


8

以下是使用 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
+1 - 我没有使用你的代码,但它帮助我找到了自己代码中的一个错误。 - Bill the Lizard

3

这个数组是否保证是按升序排列的?如果是,可以尝试使用std::lower_bound


是的,它保证以升序出现。std::lower_bound 起了作用,谢谢。 - Bill the Lizard

3
我认为我的示例恰好符合您的要求:
(我使用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
}

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接