Оператор отношения

редактировать

В информатике оператор отношения является языком программирования или оператор , который проверяет или определяет какое-то отношение между двумя объектами. К ним относятся числовое равенство (например, 5 = 5) и неравенства (например, 4 ≥ 3).

В языках программирования, которые включают отдельный логический тип данных в свою систему типов, например Pascal, Ada, или Java, эти операторы обычно оцениваются как истинные или ложные, в зависимости от того, выполняется ли условная связь между двумя операндами или нет. В таких языках, как C, операторы отношения возвращают целые числа 0 или 1, где 0 означает ложь, а любое ненулевое значение означает истину.

Выражение , созданное с использованием оператора отношения, формирует то, что называется выражением отношения или условием. Операторы отношения можно рассматривать как частные случаи логических предикатов .

Содержание
  • 1 Равенство
    • 1.1 Использование
    • 1.2 Сходство (идентичность объекта) и равенство содержимого
    • 1.3 Сравнение значений разных типов
  • 2 Упорядочивание
  • 3 Логическая эквивалентность
  • 4 Стандартные реляционные операторы
  • 5 Синтаксис
    • 5.1 Цепочка операторов
    • 5.2 Путаница с операторами присваивания
      • 5.2.1 B и C
      • 5.2.2 Языки
  • 6 См. Также
  • 7 Примечания и ссылки
Равенство

Использование

Равенство используется во многих конструкциях языков программирования и типах данных. Он используется для проверки того, существует ли уже элемент в наборе , или для доступа к значению с помощью ключа. Он используется в операторах переключателя для направления потока управления в нужную ветвь и во время процесса унификации в логическом программировании.

Одно из возможных значений равенства состоит в том, что «если a равно b, то либо a, либо b могут использоваться взаимозаменяемо в любом контексте, не замечая никакой разницы». Но это утверждение не обязательно верно, особенно если принять во внимание изменчивость вместе с равенством содержания.

Сходство (идентичность объекта) и равенство содержимого

Иногда, особенно в объектно-ориентированном программировании, сравнение вызывает вопросы о типах данных и наследование, равенство и идентичность. Часто бывает необходимо различать:

  • два разных объекта одного и того же типа, например, две руки
  • два одинаковых, но различных объекта, например, две банкноты по 10 долларов
  • два объекта, являющиеся равные, но имеющие разное представление, например, банкнота в 1 доллар и монета в 1 доллар
  • две разные ссылки на один и тот же объект, например, два псевдонима для одного и того же человека

Во многих современных языках программирования, объекты и структуры данных доступны через ссылки. В таких языках возникает необходимость проверки двух различных типов равенства:

  • Физическое равенство: если две ссылки (A и B) ссылаются на один и тот же объект. Взаимодействия с объектом через A неотличимы от тех же взаимодействий через B, и, в частности, изменения объекта через A отражаются через B. Физическая идентичность не применима, когда речь идет о значениях вместо объектов.
  • Семантическое равенство : если объекты, на которые ссылаются две ссылки, или два значения эквивалентны в некотором смысле:
  • Структурное равенство (т. е. их содержимое одинаково). который может быть либо поверхностным (тестирование только непосредственных частей), либо глубоким (проверка равенства частей рекурсивно). Простым способом добиться этого является репрезентативное равенство: проверка того, что значения имеют одинаковое представление.
  • Некоторое другое индивидуализированное равенство, сохраняющее внешнее поведение. Например, 1/2 и 2/4 считаются равными, если рассматривать их как рациональное число. Возможное требование: «A = B тогда и только тогда, когда все операции с объектами A и B будут иметь одинаковый результат», в дополнение к рефлексивности, симметрии и транзитивность.

Первый тип равенства обычно подразумевает второй (за исключением таких вещей, как не число (NaN ), которые не равны самим себе), но обратное не обязательно верно. Например, два объекта string могут быть разными объектами (неравными в первом смысле), но содержать одну и ту же последовательность символов (равными во втором смысле). Подробнее об этой проблеме см. identity.

Действительные числа, включая множество простых дробей, не могут быть точно представлены в арифметике с плавающей запятой, и может потребоваться проверка на равенство в пределах заданного допуска. Однако такой допуск может легко нарушить желаемые свойства, такие как транзитивность, тогда как рефлексивность также нарушается: стандарт IEEE с плавающей запятой требует, чтобы выполнялось NaN ≠ NaN.

Другие элементы программирования, такие как вычислимые функции, могут либо не иметь смысла равенства, либо равенство невычислимое. По этим причинам некоторые языки определяют явное понятие «сопоставимого» в форме базового класса, интерфейса, признака или протокола, которое используется либо явно, путем объявления в исходном коде, либо неявно через структуру вовлеченного типа.

Сравнение значений разных типов

В JavaScript, PHP, VBScript и некоторых других с динамической типизацией языков, стандартный оператор равенства принимает значение «истина», если два значения равны, даже если они имеют разные типы, в результате чего число 4 сравнивается, например, с текстовой строкой «4». Типизированный оператор равенства также часто доступен в таких языках, возвращающий истину только для значений с идентичными или эквивалентными типами (в PHP, 4 === "4"ложно, хотя 4 == " 4 "верно). Для языков, где число 0 может интерпретироваться как ложь, этот оператор может упростить такие вещи, как проверка нуля (поскольку x == 0будет истинным для x, равного 0 или "0", с использованием типа агностик оператор равенства).

Упорядочивание

Сравнение нечисловых данных больше и меньше, чем выполняется в соответствии с соглашением о сортировке (например, для текстовых строк лексикографический порядок ), который может быть встроенным в язык программирования и / или настраиваться программистом.

Когда требуется связать числовое значение с результатом сравнения двух элементов данных, скажем, a и b, обычным соглашением является присвоение -1, если a < b, 0 if a = b and 1 if a>b. Например, функция C strcmp выполняет трехстороннее сравнение и возвращает -1, 0 или 1 в соответствии с этим соглашением, а qsort ожидает, что функция сравнения вернет значения в соответствии с этим соглашением. В алгоритмах сортировки эффективность кода сравнения имеет решающее значение, поскольку это один из основных факторов, влияющих на производительность сортировки.

Сравнение определенных программистом типов данных (типов данных, для которых язык программирования не имеет встроенного понимания) может выполняться с помощью специально написанных или библиотечных функций (например, strcmp, упомянутого выше), или, в некоторых языках, путем перегрузки оператора сравнения, то есть присвоения значения, определенного программистом, которое зависит от сравниваемых типов данных. Другой альтернативой является использование некоторого соглашения, такого как сравнение по элементам.

Логическая эквивалентность

Хотя поначалу это может быть неочевидно, как, например, булевы логические операторы XOR, AND, OR и NOT, операторы отношения могут быть разработан так, чтобы иметь логическую эквивалентность, так что все они могут быть определены в терминах друг друга. Следующие четыре условных оператора имеют одинаковую логическую эквивалентность E (либо все истинные, либо все ложные) для любых заданных значений x и y:

E = {x < y y>xx ≱ yy ≰ x {\ displaystyle E = {\ begin {case} x x \\ x \ ngeq y \\ y \ nleq x \ end {cases}}}E={\begin{cases}x<y\\y>x \\ x \ ngeq y \\ y \ nleq x \ end { case}}

Это полагается на домен хорошо упорядочен.

Стандартные операторы отношения

Наиболее распространенные числовые операторы отношения, используемые в языках программирования, показаны ниже.

Общие операторы отношения
Соглашениеравноне равнобольшеменьшебольше. или равноменьше. или равно
В печати=><
FORTRAN .EQ..NE..GT..LT..GE..LE.
АЛГОЛ 68 =><
/=>=<=
eqnegtltgele
APL =><
BASIC, ML, Паскаль =<>><>=<=
MUMPS ='=><'<'>
Lua ==~=><>=<=
C-подобный ==!=><>=<=
Erlang ==/=><>==<
=: == / =
Борноподобные оболочки -eq-ne-gt-lt-ge-le
Пакетный файл EQUNEQGTRLSSGEQLEQ
MATLAB ==~=><>=<=
eq (x, y)ne (x, y)gt (x, y)lt (x, y)ge (x, y)le (x, y)
Fortran 90, Haskell ==/=><>=<=
Mathematica ==!=><>=<=
Равно [x, y]Неравно [x, y]Больше [x, y]Меньше [x, y]БольшеРавно [x, y]LessEqual [x, y]

Другие соглашения менее распространены: Common Lisp и Macsyma / Maxima используют операторы типа Basic, за исключением неравенства, которое / =в Common Lisp и #в Macsyma / Maxima. В старом Лиспе использовалось равное, большеpи меньшеp; и инвертировал их, используя , а недля остальных операторов.

Синтаксис

Операторы отношения также используются в технической литературе вместо слов. Операторы отношения обычно записываются в инфиксной нотации, если это поддерживается языком программирования, что означает, что они появляются между своими операндами (два связанных выражения). Например, выражение в Python напечатает сообщение, если x меньше y:

if x < y: print("x is less than y in this example")

. В других языках программирования, таких как Lisp, используется префиксная нотация , следующим образом:

(>= XY)

Цепочка операторов

В математике обычной практикой является объединение реляционных операторов в цепочку, например, в 3 < x < y < 20 (meaning 3 < x and x < y and y < 20). The syntax is clear since these relational operators in mathematics are transitive.

. Однако многие современные языки программирования увидят выражение типа 3 < x < y as consisting of two left (or right-) associative operators, interpreting it as something like (3 < x) < y. Если мы скажем, что x = 4, тогда мы получим (3 < 4) < y, и оценка даст true , что обычно не имеет смысл. Тем не менее, он компилируется на C / C ++ и некоторых других языках, давая удивительный результат (поскольку истина будет представлена ​​здесь числом 1).

Выражению x < y < zможно присвоить его знакомый математический смысл, и некоторые языки программирования, такие как Python и Raku, делают это. Другие, такие как C # и Java, этого не делают, отчасти потому, что это будет отличаться от того, как большинство других инфиксных операторов работают в C-подобном языков. D программирование la nguage этого не делает, поскольку он поддерживает некоторую совместимость с C, и «разрешение выражений C, но с несколько иной семантикой (хотя, возможно, в правильном направлении) добавило бы больше путаницы, чем удобства».

Некоторые языки, как и Common Lisp, используйте для этого предикаты с несколькими аргументами. В Лиспе (<= 1 x 10)истинно, когда x находится между 1 и 10.

Путаница с операторами присваивания

Ранний FORTRAN (1956–57) был ограничен сильно ограниченными наборами символов, где =был единственным доступным оператором отношения. Не было <или >(и уж точно не было или ). Это вынудило дизайнеров определить такие символы, как .GT., .LT., .GE., .EQ.и т. Д. и впоследствии было заманчиво использовать оставшийся символ =для копирования, несмотря на очевидную несогласованность с математическим использованием (X = X + 1должно быть невозможно).

Международный алгебраический язык (IAL, ALGOL 58 ) и ALGOL (1958 и 1960), таким образом, ввели : =для присвоения, оставив стандарт =доступно для равенства, за соглашением следуют CPL, ALGOL W, ALGOL 68, базовый комбинированный язык программирования (BCPL ), Simula, SET Language (SETL ), Pascal, Smalltalk, Modula-2, Ada, Standard ML, OCaml, Eiffel, Object Pascal (Delphi ), Oberon, Dylan, VHSIC Hardware Description Language (VHDL ) и несколько других языков.

B и C

Этот единый де-факто стандарт среди большинства языков программирования был в конечном итоге изменен, косвенно, минималистским компилируемым языком с именем B. Его единственным предполагаемым приложением было средство для первого порта (тогда очень примитивного) Unix, но оно также превратилось в очень влиятельный язык C.

B начинался как синтаксически измененный вариант языка системного программирования BCPL, упрощенная (и безтиповая) версия CPL. В процессе, который был описан как «разборка», операторы ии илиBCPL были заменены на и |(который позже станет и ||соответственно.). В том же процессе стиль ALGOL : =в BCPL был заменен на =в B. Причина всего этого неизвестна. Поскольку обновления переменных не имели специального синтаксиса в B (например, letили аналогичного) и были разрешены в выражениях, это нестандартное значение знака равенства означало, что теперь необходимо было связать традиционную семантику знака равенства с другим символом. Кен Томпсон использовал для этого специальную комбинацию ==.

Поскольку позже была представлена ​​небольшая система типов, B затем стал C. Популярность этого языка вместе с его ассоциацией с Unix привела к тому, что Java, C # и многие другие языки последовали его примеру, синтаксически, несмотря на это ненужное противоречит математическому значению знака равенства.

Языки

Присваивания в C имеют значение, и поскольку любое ненулевое скалярное значение интерпретируется как истинное в условных выражениях, код if (x = y)допустимо, но имеет совсем другое значение, чем if (x == y). Предыдущий фрагмент кода означает «присвоить y переменной x, и если новое значение x не равно нулю, выполнить следующую инструкцию». Последний фрагмент означает «тогда и только тогда, когда x равно y, выполнить следующий оператор».

int x = 1; int y = 2; if (x = y) {/ * Этот код всегда будет выполняться, если y не равно 0 * / printf ("x равно% d, а y равно% d \ n", x, y); }

Хотя Java и C # имеют те же операторы, что и C, эта ошибка обычно вместо этого вызывает ошибку компиляции на этих языках, потому что условие if должно иметь тип boolean, и не существует неявного способа преобразования из других типов (например, чисел) в booleans. Поэтому, если переменная, присвоенная переменной, не имеет тип boolean(или тип оболочки Boolean), возникнет ошибка компиляции.

В АЛГОЛ-подобных языках, таких как Pascal, Delphi и Ada (в том смысле, что они допускают определения вложенных функций ), а также в Python и многих функциональных языков, среди прочего, операторы присваивания не могут появляться в выражении (включая предложения if), что исключает этот класс ошибок. Некоторые компиляторы, такие как GNU Compiler Collection (GCC), выдают предупреждение при компиляции кода, содержащего оператор присваивания внутри оператора if, хотя есть некоторые допустимые варианты использования присваивания внутри условия if. В таких случаях назначение должно быть заключено в дополнительную пару круглых скобок явно, чтобы избежать предупреждения.

Аналогично, некоторые языки, такие как BASIC, используют только символ =как для присваивания, так и для равенства, поскольку они синтаксически разделены (как в Pascal, Ada, Python и т. д., операторы присваивания не могут появляться в выражениях).

У некоторых программистов есть привычка писать сравнения с константами в обратном обычному порядку:

if (2 == a) {/ * Ошибочное использование = versus == было бы компиляцией -time error * /}

Если =используется случайно, полученный код недействителен, поскольку 2 не является переменной. Компилятор выдаст сообщение об ошибке, в котором можно заменить соответствующий оператор. Этот стиль кодирования называется левосторонним сравнением или условиями Йоды.

В этой таблице перечислены различные механизмы для проверки этих двух типов равенства на разных языках:

ЯзыкФизическое равенствоСтруктурное равенствоПримечания
АЛГОЛ 68 a: =: bили a равно ba = b, когда aи b- указатели
C, C ++ a == b* a == * b, когда aи b- указатели
C# object.ReferenceEquals (a, b)a.Equals (b)Оператор ==по умолчанию имеет значение ReferenceEquals, но может быть перегруженным для выполнения вместо этого Equals.
Common Lisp (eq ab)(equal ab)
Erlang a =: = ba == bкогда a и b - числа
Go a == breflection.DeepEqual (* a, * b)когда a и b являются указателями
Java a == ba.equals (b)
JavaScript a === ba == bкогда a и b - два строковых объекта, содержащие эквивалентные символы, оператор === все равно вернет true.
OCaml, Smalltalk a == ba = b
Паскаль a ^ = b ^a = b
Perl $ a == $ b$$ a == $$ bкогда $ aи $ bявляются ссылками на скаляры
PHP $ a === $ b$ a == $ bкогда $ aи $ bявляются объектами
Python a is ba == b
Ruby a.equal? ​​(b)a == b
Схема (eq? ab)(equal? ​​ab)
Swift a === ba == bкогда a и b имеют тип класса
Visual Basic.NET a Является объектом bили .ReferenceEquals (a, b)a = bили a.Equals (b)То же, что и C #
Objective-C (Cocoa, GNUstep )a == b[a isEqual: b]когда aи b- указатели на объекты, которые являются экземплярами NSObject

Ruby использует a === bдля обозначения «b является членом множества a», хотя детали того, что значит быть членом, значительно различаются в зависимости от задействованных типов данных. = ==здесь известен как оператор «равенства случаев» или «подчинение вариантов».

См. Также
Примечания и ссылки
Последняя правка сделана 2021-06-03 12:16:29
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте