问题
What I am trying to accomplish is iterating through a vector of double values and returning the vector position of the closest possible double. I am having two issues with this.
When attempting to find the closest double value in the vector using
lower_bound()
, i only receive a value other than zero if I enter 1.I am not sure how to use
lower_bound
to return a vector position instead of a double value.
Here is my three main files I am using with attempted code
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;
}
Update: So I am still attempting to use lower_bound(). Here is my updated function.
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())];
}
Currently the if I input a float value I am still not able to recieve the correct vector value, it either returns 0 or the [0] vector value.
Update 2: text values
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
回答1:
You can use min_element with a comparator that takes the distance to value
into account:
// 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;
}
回答2:
lower_bound() does not return an iterator to the closest value. It returns an iterator to the first element which does not go before your value, i.e. in this case the first element >= 5.000
One way to solve this, if you want to use lower_bound()
etc :
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)
The above code can be reduced to this equivalent code:
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;
}
There are more compact ways to go about this sort of problem, but this illustrates how to solve the problem at hand by using relatively simple concepts.
The time complexity of lower_bound()
and upper_bound()
is quite good, too.
来源:https://stackoverflow.com/questions/54056171/find-closest-value-in-vector