В чем разница между равенством и эквивалентностью?
Я прочитал несколько примеров в чтении математики и информатики, которые используют символ эквивалентности ≡
, (в основном '=' с тремя строками), и мне всегда имеет смысл читать это, как если бы это было равенство. В чем разница между этими двумя понятиями?
10 ответов
Википедия: Соотношение эквивалентности:
В математике отношение эквивалентности - это бинарное отношение между двумя элементами множества, которое группирует их как "эквивалентные" в некотором роде. Пусть a, b и c - произвольные элементы некоторого множества X. Тогда "a ~ b" или "a ≡ b" означает, что a эквивалентно b.
Отношение эквивалентности "~" рефлексивно, симметрично и транзитивно.
Другими словами, = это просто пример отношения эквивалентности.
Редактировать: Этот, казалось бы, простой критерий рефлексивности, симметрии и переходности не всегда тривиален. См. Эффективная Java Блоха, 2-е изд. 35 например,
public final class CaseInsensitiveString {
...
// broken
@Override public boolean equals(Object o) {
if (o instance of CaseInsensitiveString)
return s.equalsIgnoreCase(
((CaseInsensitiveString) o).s);
if (o instanceof String) // One-way interoperability!
return s.equalsIgnoreCase((String) o);
return false;
}
...
}
Вышеуказанная равная реализация нарушает симметрию, потому что CaseInsensitiveString
знает о String
класс, но String
класс не знает о CaseInsensitiveString
,
Я принимаю ваш вопрос скорее о математической нотации, чем о программировании. Тройной знак равенства, на который вы ссылаетесь, можно записать ≡
в HTML или \equiv
в латексе.
a ≡ b чаще всего означает "a определено как b" или "пусть a будет равно b".
Таким образом, 2+2=4, но φ ≡ (1+sqrt(5))/2.
Вот удобная таблица эквивалентности:
Mathematicians Computer scientists
-------------- -------------------
= ==
≡ =
(Другие ответы об отношениях эквивалентности тоже верны, но я не думаю, что они такие же общие. Есть также ≡ b (mod m), который произносится как "a соответствует b, mod m", и на языке программиста будет выражаться как mod(a,m) == mod(b,m). Другими словами, a и b равны после mod'ing с помощью m.)
Многие языки различают равенство объектов и равенство значений этих объектов.
Например, в Ruby есть 3 различных способа проверки равенства. Первая, равная?, Сравнивает две переменные, чтобы увидеть, указывают ли они на один и тот же экземпляр. Это эквивалентно в языке C-стиля делать проверку, чтобы видеть, ссылаются ли 2 указателя на тот же адрес. Второй метод, ==, проверяет равенство значений. Так что 3 == 3,0 будет верно в этом случае. Третий, eql?, Сравнивает как значение, так и тип класса.
Лисп также имеет разные концепции равенства в зависимости от того, что вы пытаетесь проверить.
В языках, которые я видел, которые различают равенство и эквивалентность, равенство обычно означает, что тип и значение одинаковы, а эквивалентность означает, что только значения одинаковы. Например:
int i = 3;
double d = 3.0;
i и d будут иметь отношение эквивалентности, поскольку они представляют одно и то же значение, но не равенство, поскольку они имеют разные типы. Другие языки могут иметь разные представления об эквивалентности (например, представляют ли две переменные один и тот же объект).
Ответы выше правильные / частично правильные, но они не объясняют, в чем именно разница. В теоретической информатике (и, вероятно, в других разделах математики) это имеет отношение к количественной оценке по свободным переменным логического уравнения (то есть, когда мы используем две записи одновременно).
Для меня лучший способ понять разницу это:
По определению
A ≡ B
средства
Для всех возможных значений свободных переменных в A и B, A = Bили же
A ≡ B <=> [A = B]
Примером
х =2x
если (на самом деле, если он такой же, как ≡)
х =0х 2х
если (потому что это не тот случай, когда x =2x для всех возможных значений x)
Ложь
Я надеюсь, что это помогает
Редактировать:
Еще одна вещь, которая пришла мне в голову, это определения двух.
A = B определяется как A <= B и A>= B, где <= (меньше равно, не подразумевает) может быть любым отношением порядка
A ≡ B определяется как A <=> B (тогда и только тогда, когда подразумевает обе стороны), стоит отметить, что импликация также является отношением порядка, и поэтому возможно (но менее точно и часто запутанно) использовать = вместо ≡.
Я предполагаю, что вывод состоит в том, что когда вы видите =, тогда вы должны выяснить намерение авторов на основе контекста.
Разница заключается, прежде всего, в уровне, на котором вводятся две концепции. "≡" является символом формальной логики, где, учитывая два предложения a и b, a ≡ b означает (a => b AND b => a).
Вместо этого '=' является типичным примером отношения эквивалентности на множестве и предполагает, по крайней мере, теорию множеств. Когда кто-то определяет конкретный набор, обычно он дает ему подходящее понятие равенства, которое приходит в форме отношения эквивалентности и использует символ "=". Например, когда вы определяете множество Q рациональных чисел, вы определяете равенство a/b = c/d (где a / b и c / d рациональны) тогда и только тогда, когда ad = bc (где ad и bc являются целыми числами)., понятие равенства для целых чисел уже было определено в другом месте).
Иногда вы можете найти неформальное обозначение f(x) ≡ g(x), где f и g - функции: это означает, что f и g имеют одну и ту же область и что f(x) = g(x) для каждого x в такой домен (это опять-таки отношение эквивалентности). Наконец, иногда вы найдете ≡ (или ~) в качестве универсального символа для обозначения отношения эквивалентности.
Возьмите это за пределы сферы программирования.
(31) равный - (имеющий такое же количество, ценность или меру, как и другой; "на равных условиях"; "все люди равны перед законом")
эквивалентно, равнозначно - (будучи по существу равным чему-то; "это было так же хорошо, как золото"; "желание было эквивалентно команде"; "его утверждение равносильно признанию вины"
По крайней мере, в моем словаре "равнозначность" означает достаточно хорошую замену для оригинала, но не обязательно идентична, и аналогично "равенство" выражает полную идентичность.
null == 0 # true , null is equivelant to 0 ( in php )
null === 0 # false, null is not equal to 0 ( in php )
(Некоторые люди используют ≈ для представления неидентичных значений)
Вы можете иметь два утверждения, которые имеют одинаковое значение истинности (эквивалент), или два утверждения, которые одинаковы (равенство). Также "знак равенства с тремя столбцами" также может означать "определяется как".
Первая проблема заключается в том, что означают в данном случае равенство и эквивалентность ? По сути, контексты вполне свободны в определении этих терминов.
Общий смысл, который я получил из различных определений, таков: для значений, называемых равными, не должно иметь значения, из какого из них вы читаете.
Самым грубым примером, нарушающим это ожидание, является C++: и говорят, что они равны , если
x == y
оценивает
true
, и называются эквивалентными , если
!(x < y) && !(y < x)
. Даже помимо определяемых пользователем перегрузок этих операторов, для чисел с плавающей запятой (
float
,
double
) это не одно и то же: все значения NaN эквивалентны друг другу (фактически эквивалентны всему), но не равны ничему, включая самих себя, а значения и сравниваются равны (и эквивалентны), хотя их можно различить, если умный.
Во многих случаях вам понадобятся лучшие термины, чтобы точно передать ваше намерение. Даны две переменные и ,
- идентичность или одинаковость для выражения того, что существует только один объект и и относятся к нему. Любое изменение, выполненное через, непреднамеренно можно наблюдать через, и наоборот. В Java переменные ссылочного типа проверяются на идентичность с помощью , в C# с помощью
ReferenceEquals
метод. В C++, если и являются ссылками,std::addressof(x) == std::addressof(y)
будет делать (тогда как&x == &y
будет работать большую часть времени, но&
могут быть настроены для пользовательских типов). - побитовое или структурное равенство для выражения того, что внутренние представления и совпадают. Обратите внимание, что побитовое равенство нарушается, когда объекты могут ссылаться (на части) самих себя внутри себя. Чтобы получить предполагаемое значение, понятие в таких случаях должно быть уточнено, чтобы сказать: структурировано одинаково. В D побитовое равенство проверяется через
is
. C имеетmemcmp
. Я не знаю ни одного языка со встроенной проверкой равенства структур. - неразличимость или заменяемость для выражения того, что значения не могут быть различимы (через их открытый интерфейс): если функция принимает два параметра и
x
а такжеy
неразличимы, звонкиf(x, y)
,f(x, x)
, а такжеf(y, y)
всегда возвращать одно и то же значение, если толькоf
проверяет идентичность (см. пункт выше) напрямую или путем мутации. Примером могут быть два дерева поиска, которые содержат неразличимые элементы, но внутренние деревья расположены по-разному, что является деталью реализации, которую нельзя наблюдать с помощью его общедоступных методов. - эквивалентность для выражения того, что объекты представляют значения, считающиеся одинаковыми из некоторых абстрактных рассуждений. В качестве примера для различимых эквивалентных значений обратите внимание, что числа с плавающей запятой имеют отрицательный нуль, отличный от , и, например,
sign(1/x)
отличается для-0.0
а также+0.0
. Эквивалентность чисел с плавающей запятой проверяется с помощью==
на многих языках с синтаксисом Algol. Большинство объектно-ориентированных языков проверяют эквивалентность объектов с помощью метода (или метода с аналогичным названием). С# имеетIEquatable<T>
интерфейс, который указывает, что класс имеет стандартное/каноническое/стандартное отношение эквивалентности, определенное для него. В Java один переопределяетequals
метод, от которого наследуется каждый классObject
.
Как видите, понятия становятся все более расплывчатыми. Проверка на идентичность — это то, что может выразить большинство языков. Программист обычно не может зацепить тождество и побитовое равенство, поскольку эти понятия не зависят от интерпретаций. Было предложение C++20, которое в конечном итоге было отклонено, которое вводило два последних понятия как сильное † и слабое равенство †. († Этот сайт выглядит как CppReference, но таковым не является; он не актуален.) Исходная статья находится здесь.
Все, что есть в C, также доступно для C++ и любого языка, который может использовать функциональность C. Все, что сказано о C#, верно для Visual Basic .NET и, возможно, для всех языков, построенных на платформе .NET. Аналогично Java представляет языки JRE.
Фактически, равенство - это особый вид отношения эквивалентности. Подумайте, что значит сказать:
0.9999999999999999... = 1
Это говорит о том, что равенство - это просто отношение эквивалентности на "строковых числах" (которые более формально определяются как функции из Z -> {0,...,9}). И мы видим из этого случая, что классы эквивалентности не являются даже синглетонами.