Передача оператора == для установки в C ++ - PullRequest
2 голосов
/ 06 февраля 2012

Я хочу получить set<double> S; и вставить несколько двойников в него.но я хочу, чтобы набор рассматривал 1.0000001 == 1.0000000 (сравнение двойных чисел с использованием epsilon) (я имею в виду, если я вставлю оба числа в набор, set.size () должен быть равен единице).Я знаю, как передать оператор () (для сравнения) в набор, но я не знаю, как передать функцию:

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

в набор.

PS: СпасибоСид.@Sid: Я обнаружил, что: operator == не используется std :: set.Элементы a и b считаются равными тогда и только тогда, когда! (A

Ответы [ 6 ]

3 голосов
/ 06 февраля 2012

Простой ответ заключается в том, что вы не можете, по крайней мере, не так легко.Вы должны определить оператор сравнения, который определяет строгий слабый порядок.Если у вас есть что-то вроде:

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;
}

Но, честно говоря, я подозреваю, что если источник ваших двойников требует такого рода вещи, они, вероятно, не подходят для хранения в set.

2 голосов
/ 06 февраля 2012

Если у вас есть функция сравнения, зачем вам оператор ==? Взгляните на следующую ветку.

std :: набор с пользовательским типом, как обеспечить отсутствие дубликатов

Посмотрите на ответ Мехрдада .

1 голос
/ 06 февраля 2012

Вам нужно квантовать свои двойники , прежде чем вставить их в набор.

Если вы считаете, что все числа в диапазоне 1.0000000 <= x <1.0000002 идентичны, просто замените все числа в этом диапазоне на 1.0000000 <strong>перед тем, как вставит их в набор. Аналогично для 1.0000002 <= x <1.0000004 и т. Д. </p>

Этот подход позволяет избежать всех проблем с операторами сравнения и транзитивностью.

1 голос
/ 06 февраля 2012

Выходя из ссылки, предоставленной @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;
}
0 голосов
/ 06 февраля 2012

Это кажется плохой идеей.Рассмотрим случай чисел 1.0000000, 1.0000001, 1.0000002.Если вы сначала введете 1.0000001, то ни один из других номеров не будет добавлен в набор.Если вы сначала добавите 1.0000000 или 1.0000002, то другой может быть добавлен позже.

Кроме того, set использует operator< для определения своего отношения, а НЕ равенства.Я не вижу способа написания строгого слабого порядка, основанного на эпсилоне, просто он не приведет к правильно отсортированному контейнеру.Контейнер использует просто для operator< или другого сравнения, и нет способа указать операцию равенства.

Лучше просто использовать обычное сравнение < и выполнить постобработку послеВы создали набор для очистки элементов, которые вам больше не нужны.Если вы дадите нам больше информации о проблеме real , которую вы пытаетесь решить, мы сможем вам помочь.

0 голосов
/ 06 февраля 2012
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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...