Найти ближайшее значение в векторе - PullRequest
0 голосов
/ 05 января 2019

То, что я пытаюсь сделать, это перебирать вектор двойных значений и возвращать векторное положение самого близкого двойника. У меня есть две проблемы с этим.

  1. При попытке найти ближайшее двойное значение в векторе, используя lower_bound(), я получаю значение, отличное от нуля, только если введу 1.

  2. Я не уверен, как использовать lower_bound, чтобы вернуть векторную позицию вместо двойного значения.

Вот мои три основных файла, которые я использую с попыткой кода

Convert.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;
}

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

Ответы [ 2 ]

0 голосов
/ 06 января 2019

lower_bound () не возвращает итератор к ближайшему значению. Он возвращает итератор к первому элементу, который не идет перед вашим значением, то есть в этом случае первый element >= 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() тоже довольно хорошая.

0 голосов
/ 06 января 2019

Вы можете использовать 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;
}
...