【问题标题】:Find Closest Value in Vector在向量中查找最接近的值
【发布时间】:2019-06-01 01:01:20
【问题描述】:

我想要完成的是遍历一个双精度值向量并返回最接近的双精度值的向量位置。我有两个问题。

  1. 当尝试使用lower_bound() 查找向量中最接近的双精度值时,如果我输入 1,我只会收到一个非零值。

  2. 我不知道如何使用lower_bound 来返回向量位置而不是双精度值。

这是我在尝试代码中使用的三个主要文件

转换.cpp

double Convert::convertmVtoK(double value)
{
    double conversion = *std::lower_bound(mV.begin(), mV.end(), value);
    cout<<"This is conversion mV to K"<<" "<< conversion;
}

double Convert::convertKtomV(double value)
{
    double conversion = *std::lower_bound(mV.begin(), mV.end(), value);
    cout<<"This is conversion K to mV"<<" "<< conversion;
}

转化率.h

class Convert
{
    public:
        Convert();
        virtual ~Convert();
        double convertmVtoK(double mV);
        double convertKtomV(double K);
        void readFile();

    protected:

    private:
        std::ifstream inFile;
        std::vector<double> kelvin,mV,sensitivity;
        double tempKelvin,tempmV,tempSensitivity;
};

#endif // CONVERT_H

Main.cpp

#include "Convert.h"
#include <stdio.h>
#include<fstream>
#include<iostream>


int main()
{
    Convert convert;
    convert.readFile();
   convert.convertmVtoK(2.0);
    convert.convertKtomV(5.000);

    return 0;
}

更新:所以我仍在尝试使用 lower_bound()。这是我更新的函数。

double Convert::convertmVtoK(double value)
{
    std::vector<double>::iterator pos;

    pos = std::lower_bound(mV.begin(), mV.end(), value);
    cout<<"This is conversion mV to K"<<" "<< kelvin[(pos-mV.begin())];
}

目前,如果我输入一个浮点值,我仍然无法接收到正确的向量值,它要么返回 0,要么返回 [0] 向量值。

更新 2:文本值

1.4 1.644290    -12.5
1.5 1.642990    -13.6
1.6 1.641570    -14.8
1.7 1.640030    -16.0
1.8 1.638370    -17.1
1.9 1.636600    -18.3
2.0 1.634720    -19.3
2.1 1.632740    -20.3

【问题讨论】:

  • lower_bound() 不会将迭代器返回到最接近的值。它返回一个迭代器到第一个不超过你的值的元素,即在这种情况下第一个元素&gt;= 5.000
  • @SidS 你能推荐使用什么而不是 lower_bound 来找到向量中最接近的值吗?
  • 遍历整个向量,跟踪最接近的值。或者,如果您要对相同的数据重复执行此操作,请对向量进行排序,然后进行二分搜索。
  • 您需要创建一个minimal reproducible example。空的构造函数和析构函数,从文件读取等与您的问题完全无关。删除所有与您发布的问题无关的内容,并将其全部制作为单个编译文件。
  • @SidS 好的,谢谢您的建议。所以我了解如何对精确值进行二进制搜索,我将如何对最接近的值进行二进制搜索?

标签: c++ vector iterator lower-bound


【解决方案1】:

您可以将min_element 与将到value 的距离考虑在内的比较器一起使用:

// precondition: mV is not empty
double get_closest(double value) const
{
    assert(!mV.empty());
    auto it = std::min_element(mV.begin(), mV.end(), [value] (double a, double b) {
        return std::abs(value - a) < std::abs(value - b);
    });
    assert(it != mV.end());

    return *it;
}

【讨论】:

  • 是的。现在,尽量避免计算两倍的std::abs(x-y) 是非常痛苦的......
  • @MarcGlisse 您是否建议仍尝试使用 lower/upper_bound 来降低时间复杂度?
  • 嗯,这需要线性时间。如果列表很长,并且您在同一个列表上进行了多次搜索,那么对数方法(在排序列表上进行二进制搜索)当然会更好。但在你测量到这是你的瓶颈之前,你不应该关心。
  • @MarcGlisse 好的,谢谢,这就是我最初尝试使用 lower/upper_bound() 的原因,因为我不需要在此列表上进行多次搜索。尽管使用 SidS 方法或我在网上找到的任何其他方法来获取向量中最接近的值的 lower/upper_bound,但我终生无法弄清楚如何获得正确的结果。
  • @C.Mock 我认为您的数据没有正确排序。
【解决方案2】:

lower_bound() 不会将迭代器返回到最接近的值。它返回一个迭代器到第一个不在你的值之前的元素,即在这种情况下第一个 element &gt;= 5.000

解决这个问题的一种方法,如果你想使用lower_bound() 等:

vector<double> v;
double d = 5.0;
auto it = lower_bound(v.begin(), v.end(), d);
if (it == v.begin())
{
    // No elements are smaller than d
    it = v.end();
}
else
{
    --it;
    // it now points to the largest element smaller than d
}

auto jt = upper_bound(v.begin(), v.end(), d);
if (jt == v.end())
{
    // No elements are larger than d
}
else
{
    // jt already points to the smallest element larger than d
}

auto out = it;
if (it == v.end())
{
    out = jt;
}
else if (jt != v.end())
{
    if (d - *it > *jt - d)
    {
        out = jt;
    }
}
// out now points to the value closest to d, or v.end() (if v is empty or only contains d)

上面的代码可以简化成这个等价的代码:

vector<double> v;
double d = 5.0;
auto it = lower_bound(v.begin(), v.end(), d);
if (it == v.begin())
{
    it = v.end();
}
else
{
    --it;
}
auto jt = upper_bound(v.begin(), v.end(), d),
     out = it;
if (it == v.end() || jt != v.end() && d - *it > *jt - d)
{
    out = jt;
}

解决这类问题有更简洁的方法,但这说明了如何使用相对简单的概念来解决手头的问题。

lower_bound()upper_bound() 的时间复杂度也相当不错。

【讨论】:

  • 谢谢!所以我成功地实现了这个,没有任何错误。但是,我要么只接收第一个或最后一个向量输出作为最接近的值。试着看看我是否能看到发生了什么
  • 可能是这里第一次使用lower_bound "auto it = lower_bound(mV.begin(), mV.end(), value);" ?如果我只使用这条线,我只会收到 0 或第一个向量值。
  • @C.Mock,我在这里发布之前测试了代码,它确实有效。如果它对您不起作用,则说明您没有正确使用它 - 或者您的数据未按升序排序。除此之外,如果没有看到您的代码和数据,我无法告诉您您的错误是什么。
  • 好的,这就是问题所在,然后我认为它正在下降。除了切换上下界之外,可以使用相同的公式吗?
  • 所以我的开尔文值是升序的,但我的电压值是降序的。我发布了包含文本值的 sn-p 的更新。
猜你喜欢
  • 2023-03-06
  • 2019-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多