std::map<String, double> m1,m2;
m1["A"] = 20;
m2["A"] = 20.01;
if (m1 == m2)
cout << "True";
else
cout << "False";
示例代码打印False,因为20不等于20.1。但是在我的应用程序中,我希望将这些值视为相等,因为这些值之间的差异具有允许的容差。那么有没有办法为数据提供自定义比较功能(而不是Key)?
感谢任何帮助。
编辑: 对不起代码中的错误。我复制了代码,我试图找到解决此问题的方法。对于我的场景,键必须相同。
答案 0 :(得分:2)
如果您关心的是整个容器的相等性,我建议使用::std::equal
算法。方法如下:
const double tolerance = 0.01;
bool equal = m1.size() == m2.size() &&
::std::equal(m1.begin(), m1.end(), m2.begin(),
[tolerance](const decltype(m1)::value_type &a,
const decltype(m2)::value_type &b) {
return (a.first == b.first) &&
(::std::abs(a.second - b.second) < tolerance);
});
如果您关心“不到”的关系,那么::std::lexicographical_compare
就是您想要的。这需要C ++ 11 lambda功能才能工作。
如果您真正想要的是以模糊方式比较相等的数据值,我会向您展示一些hack(以及还需要几个C ++ 11特性的东西)fuzzy-double.cpp
。我禁用了排序比较,因为这会诱使你在订购容器中填充这些东西,而(2.0 == 2.1) && (2.1 == 2.2)
,但是(2.0 != 2.2)
,它们不适用于此目的。
#include <cmath>
#include <iostream>
template <const double &tolerance>
class fuzzy_double {
public:
fuzzy_double(double x) : x_(x) {
static_assert(tolerance >= 0, "tolerance must be >= 0");
}
operator double() const { return x_; }
const fuzzy_double &operator =(double x) { x_ = x; }
bool equals(const fuzzy_double &b) const {
return ::std::abs(x_ - b.x_) <= tolerance;
}
// This cannot be used as the basis of a 'less than' comparison operator for
// the purposes of other algorithms because it's possible for a transitive
// equality relationship to exit that equates all fuzzy_double's to
// eachother. There is no strict ordering that makes sense.
bool fuzzy_less(const fuzzy_double &b) const {
return (b.x_ - x_) > tolerance;
}
private:
double x_;
};
template <const double &tolerance>
bool operator ==(const fuzzy_double<tolerance> &a,
const fuzzy_double<tolerance> &b)
{
return a.equals(b);
}
template <const double &tolerance>
bool operator !=(const fuzzy_double<tolerance> &a,
const fuzzy_double<tolerance> &b)
{
return !a.equals(b);
}
template <const double &tolerance>
bool operator <(const fuzzy_double<tolerance> &a,
const fuzzy_double<tolerance> &b)
{
// tolerance < 0 should be an impossible condition and always be false, but
// it's dependent on the template parameter and so only evaluated when the
// template is instantiated.
static_assert(tolerance < 0, "fuzzy_doubles cannot be ordered.");
return false;
}
template <const double &tolerance>
bool operator >=(const fuzzy_double<tolerance> &a,
const fuzzy_double<tolerance> &b)
{
// tolerance < 0 should be an impossible condition and always be false, but
// it's dependent on the template parameter and so only evaluated when the
// template is instantiated.
static_assert(tolerance < 0, "fuzzy_doubles cannot be ordered.");
return false;
}
template <const double &tolerance>
bool operator >(const fuzzy_double<tolerance> &a,
const fuzzy_double<tolerance> &b)
{
// tolerance < 0 should be an impossible condition and always be false, but
// it's dependent on the template parameter and so only evaluated when the
// template is instantiated.
static_assert(tolerance < 0, "fuzzy_doubles cannot be ordered.");
return false;
}
template <const double &tolerance>
bool operator <=(const fuzzy_double<tolerance> &a,
const fuzzy_double<tolerance> &b)
{
// tolerance < 0 should be an impossible condition and always be false, but
// it's dependent on the template parameter and so only evaluated when the
// template is instantiated.
static_assert(tolerance < 0, "fuzzy_doubles cannot be ordered.");
return false;
}
extern constexpr double ten_e_minus_2 = 0.01;
int main()
{
fuzzy_double<ten_e_minus_2> a(3);
fuzzy_double<ten_e_minus_2> b(3.009);
fuzzy_double<ten_e_minus_2> c(2.991);
fuzzy_double<ten_e_minus_2> d(3.011);
fuzzy_double<ten_e_minus_2> e(2.989);
using ::std::cout;
cout << "a == a: " << (a == a) << '\n';
cout << "a == b: " << (a == b) << '\n';
cout << "a == c: " << (a == c) << '\n';
cout << "a == d: " << (a == d) << '\n';
cout << "a == e: " << (a == e) << '\n';
return 0;
}
C ++ 11不允许double
,甚至const
一个成为模板参数。 OTOH允许指针和对具有外部链接的对象的引用作为模板参数。因此,如果您将公差声明为extern constexpr double
,则可以使用命名公差作为模板参数。
答案 1 :(得分:1)
您正在比较两个完全独立的地图,其中包含不同的键和值。我很确定这不是你的意图。
您可以使用键的自定义比较操作制作地图,以回答我认为您要求的内容,但使用变量容差制作一个可能无法正常工作。 STL对低于和等于的含义以及它们必须如何表现有严格的要求;如果您违反规则,您的地图将随机失败。所以我不会为此使用地图。在您的情况下,您对值而不是键感兴趣,在这种情况下,STL根本不关心(它根本不会查看您的值)。
答案 2 :(得分:1)
您可以将lexicographical_compare
与自定义比较对使用,忽略值中的微小差异,如下所示:
bool mycomp (pair<string,double> lhs, pair<string,double> rhs) {
if (lhs.first < rhs.first) {
return true;
}
if (lhs.first > rhs.first) {
return false;
}
// Here is the "check tolerance" part:
if (abs(lhs.second-rhs.second) < 0.05) {
return false;
}
return lhs.second < rhs.second;
}
int main() {
std::map<string, double> m1,m2;
m1["A"] = 20;
m2["A"] = 20.01;
bool res = lexicographical_compare(
m1.begin(), m1.end(),
m2.begin(), m2.end(),
mycomp
);
cerr << res << endl;
return 0;
}
答案 3 :(得分:0)
当您将M1与M2进行比较时,您将相互比较地图,而不是地图中的值。如果你想比较双打,可以看一下this post。