与下面的链接类似,
https://stackoverflow.com/a/30424281/1442787
我的班级Point
包含成员变量double x,y,z
。
我在课程中重载operator <
以将值插入std::map
bool Point::operator<(const Point &p)const{
return ( x < p.x
|| ( x == p.x
&& ( y < p.y
|| ( y == p.y
&& z < p.z))));
}
我已将Point类定义为键,将std::pair
定义为值
typedef std::pair<int,int> mypair;
typedef std::map<Point, mypair> mymap;
std::map
不允许插入重复的密钥。
但是,在我的代码中,插入键/值对时,重复键也会被插入,如下所示
map:0.436612,16.527741,0.000000,22,2 map:0.454781,17.427262,15.264347,74,12 map:0.454781,17.427262,15.264347,27,11 map:0.608370,17.373443,20.124160,21,13 map:0.608370,17.373443,20.124160,69,11
重复插入的原因是什么?
答案 0 :(得分:0)
你的问题是浮点值很少比较相等,特别是如果它们是计算的结果(但是在更平凡的情况下它们可能是不相等的,因为它们在内存中存储的大小不同于寄存器中的大小)。
首先,您应该避免使用浮点作为键。
如果你真的想要这样做,那么你应该有一些特定领域的比较运算符。您可以使用epsilon-tolerance(如果abs(x - y) < e
,则两个浮点数相等,其中e
是一个小值),或者您可以使用与数字一致的容差值(基本上,产生类似“两个数字等于一定数量的有效数字“)。单元测试库(例如the Boost Test library)使用这些类型的比较。对于点,您可以使用基于距离的相等:两个点相等,如果它们彼此更接近而不是某个值。
以前我提到了等式谓词。你可以像这样进行比较:
bool Point::operator==(const point &p)const{
// Using Manhattan distance here.
return (x - p.x) + (y - p.y) + (z - p.z) < 0.0001;
}
bool Point::operator<(const Point &p)const{
return p != *this && ( x < p.x
|| ( x == p.x
&& ( y < p.y
|| ( y == p.y
&& z < p.z))));
}
答案 1 :(得分:-1)
我建议您使用std::multimap
,因为它可以存储重复值...
如果你想确保你要添加的给定点不在现有点的小容差范围内,那么我会检查x
坐标在公差范围内的任何点。
因此,要找到这一点,您可以创建一个点:
Point search { x - tolerance, -Inf, -Inf };
然后使用lower_bound
作为起点并测试任何后续点,直到其x
坐标大于x + tolerance
。