传递运算符 == 在 c++ 中设置

发布于 2025-01-03 18:11:00 字数 452 浏览 5 评论 0原文

我想要一个 setS; 并向其中插入一些双精度数。但我希望集合考虑 1.0000001 == 1.0000000 (使用 epsilon 比较双精度数)(我的意思是,如果我将两个数字插入集合中,set.size() 应等于 1)。我知道如何将 operator() (用于比较)传递给集合,但我不知道如何将 function:

const double eps = 1e-8;
bool operator==(double a, double b)
{
    return abs(a - b) < eps;
}

传递给集合。

PS:感谢席德。 @Sid:我发现:std::set 不使用operator==。元素 a 和 b 被视为相等 iff !(a < b) && !(b<a)。

I want to have a set<double> S; and insert some doubles into it. but I want the set to consider 1.0000001 == 1.0000000 (comparing doubles using epsilon) (I mean if I insert both of the numbers to the set, set.size() should equal to one). I know how to pass the operator() (for comparing) to the set but I don't know how to pass the function:

const double eps = 1e-8;
bool operator==(double a, double b)
{
    return abs(a - b) < eps;
}

to the set.

P.S: Thanks to Sid. @Sid: I found out that: operator== is not used by std::set. Elements a and b are considered equal iff !(a < b) && !(b < a).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

放飞的风筝 2025-01-10 18:11:00

简单的答案是你不能,至少不能那么容易。你
必须定义一个比较运算符,它定义了严格的弱
订购。如果你有类似的东西:

bool
cmpDouble( double lhs, double rhs )
{
    return abs( lhs - rhs ) < eps
        ? false
        : lhs < rhs;
}

那么! (a < b) && ! (b < a) 没有定义等价
关系,因此不满足主要要求。

可以使用类似的东西:

bool
cmpDouble( double lhs, double rhs )
{
    double iLhs;
    modf( 1e8 * lhs, &iLhs );
    double iRhs;
    modf( 1e8 * rhs, &iRhs );
    return iLhs < iRhs;
}

但坦率地说,我怀疑如果你的双打来源需要这个
诸如此类的事情,它们可能不适合存储在集合中。

The simple answer is that you can't, at least not that easily. You
have to define a comparison operator which defines a strict weak
ordering. If you have something like:

bool
cmpDouble( double lhs, double rhs )
{
    return abs( lhs - rhs ) < eps
        ? false
        : lhs < rhs;
}

then ! (a < b) && ! (b < a) doesn't define an equivalence
relationship, so a major requirement isn't met.

It's possible to use something like:

bool
cmpDouble( double lhs, double rhs )
{
    double iLhs;
    modf( 1e8 * lhs, &iLhs );
    double iRhs;
    modf( 1e8 * rhs, &iRhs );
    return iLhs < iRhs;
}

But frankly, I suspect that if the source of your doubles requires this
sort of thing, they probably aren't appropriate for storing in a set.

献世佛 2025-01-10 18:11:00

如果你有比较函数那么为什么还需要operator==?看看下面的线程。

std::set 具有用户定义的类型,如何确保没有重复项

请参阅Mehrdad 的回答

If you have the comparison function then why do you need operator== ? Take a look at the following thread.

std::set with user defined type, how to ensure no duplicates

Look at Mehrdad's answer.

别念他 2025-01-10 18:11:00

离开@Sid提供的链接,似乎(无论明智或不明智),您可以通过定义比较运算符来做到这一点,如下所示:

const double eps = 1e-8;
bool less_than(double a, double b)
{
    return a < b - eps;
}

bool greater_than(double a, double b)
{
    return a > b + eps;
}

Going off the link provided by @Sid, it seems that (however well- or ill-advised it is), you can do this by defining your comparison operators as follows:

const double eps = 1e-8;
bool less_than(double a, double b)
{
    return a < b - eps;
}

bool greater_than(double a, double b)
{
    return a > b + eps;
}
紫南 2025-01-10 18:11:00

您需要在将双打插入集合之前对其进行量化。

如果考虑 1.0000000 <= x < 范围内的所有数字1.0000002 是相同的,只需将这个范围内的所有数字替换为 1.0000000 将其插入集合中即可。同样对于 1.0000002 <= x < 1.0000004 等。

这种方法避免了比较运算符和传递性的所有问题。

You need to quantize your doubles before inserting them into the set.

If you consider all numbers in the range 1.0000000 <= x < 1.0000002 to be identical, simply replace all numbers in this range by 1.0000000 before inserting them into the set. Likewise for 1.0000002 <= x < 1.0000004 etc.

This approach avoids all issues with comparison operators and transitivity.

这似乎是个坏主意。考虑数字 1.00000001.00000011.0000002 的情况。如果您首先插入 1.0000001,则其他数字都不允许添加到该集合中。如果您先添加 1.00000001.0000002,则可以稍后添加另一个。

此外,set 使用operator< 来定义其关系,而不是相等。我看不到一种编写依赖于 epsilon 的严格弱排序的方法,它只是不会产生正确排序的容器。容器依赖于运算符<或其他比较,并且无法指定相等运算。

更好的方法是仅使用正常的 < 比较,并在构建集合后进行后处理以清理不再需要的元素。如果您向我们提供有关您试图解决的真实问题的更多信息,我们也许能够提供帮助。

This seems like a bad idea. Consider the case of the numbers 1.0000000, 1.0000001, 1.0000002. If you insert 1.0000001 first then neither of the other numbers would be allowed to be added to the set. If you add 1.0000000 or 1.0000002 first then the other could be added later.

Additionally, set uses operator< to define its relationship, NOT equality. I can't see a way of writing a strict weak ordering that relies on an epsilon, it's just not going to result in a properly sorted container. The container relies just on operator< or other comparison and there's no way of specifying an equality operation.

Better is to just use the normal < comparison and do post-processing after you've built the set to clean up the elements you don't want anymore. If you give us more information about the real problem you're trying to solve we may be able to help.

风向决定发型 2025-01-10 18:11:00
const double eps = 1e-8;
bool compare(double a, double b)
{
    return (abs(a - b) > eps) ? (a < b) : false;
}

set<int,bool(*)(double,double)> set (compare);

struct Compare
{
    bool operator()(double a, double b) const
    {
        return (abs(a - b) > eps) ? (a < b) : false;
    }
};

set<int,Compare> set;
const double eps = 1e-8;
bool compare(double a, double b)
{
    return (abs(a - b) > eps) ? (a < b) : false;
}

set<int,bool(*)(double,double)> set (compare);

struct Compare
{
    bool operator()(double a, double b) const
    {
        return (abs(a - b) > eps) ? (a < b) : false;
    }
};

set<int,Compare> set;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文