获取最接近 std::vector 双打值的项目
Get item closest to a value in a std::vector of doubles
在 C++ 11 中是否有一种优雅的方法可以从最接近某个值的 double
中的 std::vector
中获取项目?
代码:
#include <iostream>
#include <vector>
double GetClosest(const std::vector<double>& vec, double value) {
// How to get the item closest to "value" from the items in vec. Vec is assumed to be sorted.
}
int main() {
std::vector<double> my_doubles_vec;
my_doubles_vec.push_back(101480.76915103197);
my_doubles_vec.push_back(101480.85708367825);
my_doubles_vec.push_back(101480.93293087184);
my_doubles_vec.push_back(101481.0027936101);
my_doubles_vec.push_back(101481.5625);
my_doubles_vec.push_back(101481.5626);
std::cout.precision(17);
std::cout << GetClosest(my_doubles_vec, 101480.76915103201) << std::endl; // Should output "101480.76915103197"
std::cout << GetClosest(my_doubles_vec, 101480.93293086279) << std::endl; // Should output "101480.93293087184"
std::cout << GetClosest(my_doubles_vec, 101481.5625) << std::endl; // Should output "101481.5625"
return 0;
}
由于它是 double
中的 std::vector
,我认为精度发挥作用了吗?还是可以用一种不需要担心精度的方式来制作逻辑?
您可以在排序范围内使用 std::partition_point
, std::lower_bound
or std::upper_bound
。
示例:
#include <algorithm>
#include <cmath>
#include <stdexcept>
double GetClosest(const std::vector<double>& vec, double value) {
if(vec.empty()) throw std::runtime_error("no elements");
// partition_point is the most generic of the three:
auto it = std::partition_point(vec.begin(), vec.end(), [value](double v) {
return v < value;
});
// or auto it = std::lower_bound(vec.begin(), vec.end(), value);
// or auto it = std::upper_bound(vec.begin(), vec.end(), value);
if(it == vec.end()) --it; // value larger than the largest in the vector
else if( it != vec.begin()) { // value not less than first
// check which one of the two around the partition point that is closest
if(std::abs(*std::prev(it) - value) < std::abs(*it - value)) --it;
}
return *it;
}
由于 vector
已排序,您可以尝试这样的操作:
#include <algorithm>
#include <cmath>
#include <stdexcept>
double GetClosest(const std::vector<double>& vec, double value) {
if (vec.empty()) throw std::invalid_argument("vector cant be empty");
if (vec.size() == 1) return vec[0];
auto iter = std::find_if(vec.begin(), vec.end(),
[=](double d){ return d >= value; }
);
if (iter == vec.begin()) return vec.front();
if (iter == vec.end()) return vec.back();
if (std::abs(value - *(iter-1)) < std::abs(value - *iter)) --iter;
return *iter;
}
在 C++ 11 中是否有一种优雅的方法可以从最接近某个值的 double
中的 std::vector
中获取项目?
代码:
#include <iostream>
#include <vector>
double GetClosest(const std::vector<double>& vec, double value) {
// How to get the item closest to "value" from the items in vec. Vec is assumed to be sorted.
}
int main() {
std::vector<double> my_doubles_vec;
my_doubles_vec.push_back(101480.76915103197);
my_doubles_vec.push_back(101480.85708367825);
my_doubles_vec.push_back(101480.93293087184);
my_doubles_vec.push_back(101481.0027936101);
my_doubles_vec.push_back(101481.5625);
my_doubles_vec.push_back(101481.5626);
std::cout.precision(17);
std::cout << GetClosest(my_doubles_vec, 101480.76915103201) << std::endl; // Should output "101480.76915103197"
std::cout << GetClosest(my_doubles_vec, 101480.93293086279) << std::endl; // Should output "101480.93293087184"
std::cout << GetClosest(my_doubles_vec, 101481.5625) << std::endl; // Should output "101481.5625"
return 0;
}
由于它是 double
中的 std::vector
,我认为精度发挥作用了吗?还是可以用一种不需要担心精度的方式来制作逻辑?
您可以在排序范围内使用 std::partition_point
, std::lower_bound
or std::upper_bound
。
示例:
#include <algorithm>
#include <cmath>
#include <stdexcept>
double GetClosest(const std::vector<double>& vec, double value) {
if(vec.empty()) throw std::runtime_error("no elements");
// partition_point is the most generic of the three:
auto it = std::partition_point(vec.begin(), vec.end(), [value](double v) {
return v < value;
});
// or auto it = std::lower_bound(vec.begin(), vec.end(), value);
// or auto it = std::upper_bound(vec.begin(), vec.end(), value);
if(it == vec.end()) --it; // value larger than the largest in the vector
else if( it != vec.begin()) { // value not less than first
// check which one of the two around the partition point that is closest
if(std::abs(*std::prev(it) - value) < std::abs(*it - value)) --it;
}
return *it;
}
由于 vector
已排序,您可以尝试这样的操作:
#include <algorithm>
#include <cmath>
#include <stdexcept>
double GetClosest(const std::vector<double>& vec, double value) {
if (vec.empty()) throw std::invalid_argument("vector cant be empty");
if (vec.size() == 1) return vec[0];
auto iter = std::find_if(vec.begin(), vec.end(),
[=](double d){ return d >= value; }
);
if (iter == vec.begin()) return vec.front();
if (iter == vec.end()) return vec.back();
if (std::abs(value - *(iter-1)) < std::abs(value - *iter)) --iter;
return *iter;
}