c++ - 具有个人比较功能的 std::set 具有相同的值

标签 c++ stdset

<分区>

我想存储一个Point3D对象的std::set,我的比较函数定义如下(字典顺序):

bool operator<(const Point3D &Pt1, const Point3D &Pt2)
{
    const double tol = 1e-5;

    if(fabs(Pt1.x() - Pt2.x()) > tol)
    {
        return Pt1.x() < Pt2.x();
    }    
    else if(fabs(Pt1.y() - Pt2.y()) > tol)
    {
        return Pt1.y() < Pt2.y();
    }
    else if(fabs(Pt1.z() - Pt2.z()) > tol)
    {
        return Pt1.z() < Pt2.z();
    }
    else
    {
        return false;
    }
}

在某些情况下,set 包含相同的点,我认为问题来自比较功能,但我没有找到确切的问题。任何帮助将不胜感激!

最佳答案

您的公差概念没有正确建立 strict weak ordering ,因为它不是传递性的。举个例子,假设公差是1 .现在考虑:

a = 1
b = 2
c = 3

此处:!(a<b)!(b<c) ,但是a<c .这明显违反了严格弱排序的传递性要求。

如果你想实现一个有公差的比较,但它也是一个严格的弱排序,你必须以一致的方式对每个值进行舍入(例如,1.5 => 20.75 => 12.3 => 2 等)然后比较四舍五入的值。

这样做似乎毫无意义,因为double我们已经这样做了,但精度最高。当你发现 1.4999999... != 1.5 时,你仍然会得到奇怪的行为。 .

你应该像下面这样写你的比较器,并放弃公差概念:

bool operator<(const Point3D &Pt1, const Point3D &Pt2)
{
    //This can be replaced with a member/free function if it is used elsewhere
    auto as_tie = [](Point3D const &Pt) {
        //assumes the member functions return references
        //to the internal `Point3D` values.
        return std::tie(Pt.x(), Pt.y(), Pt.z());
    };
    return as_tie(Pt1) < as_tie(Pt2);
}

如果您绝对必须有容差,请在将值放入 Point3D 后立即对其进行舍入,或在比较前四舍五入值(取决于系统中的其他要求)。

关于c++ - 具有个人比较功能的 std::set 具有相同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24118446/

相关文章:

c++ - 如何在 C++ 中做集合 vector ?

c++ - 从函数返回 char*

c++ - 为什么 float 和 int 的 std::pow 会调用此重载?

c++ - 值得产生一个新线程的最小工作量

c++ - std::set 不检测重复的自定义对象

c++ - 自定义结构错误 : "VS 2015 error C2678: binary ' <': no operator found which takes a left-hand operand of type ' const Node'"

c++ - 运行 shellcode + vs2010

c++ - 实时音频(发送和接收)的好库?

c++ - 为什么类型推导对我的集合交集和集合差异调用不起作用?

c++ - 错误: passing x as 'this' argument of x discards qualifiers