Введение

Конструкция языка программирования

В информатике реляционный оператор — это конструкция или оператор языка программирования, который проверяет или определяет определенное отношение между двумя сущностями. К ним относятся равенство (например, ==) и неравенство (например, 4 ≥ 3). В языках программирования, которые включают в свою систему типов отдельный булев тип данных, таких как Паскаль, Ада или Java, эти операторы обычно возвращают значение "истина" или "ложь" в зависимости от того, выполняется ли заданное отношение между двумя операндами. В языках, таких как C, реляционные операторы возвращают целые числа 0 или 1, где 0 представляет "ложь", а любое ненулевое значение представляет "истину". Выражение, созданное с использованием реляционного оператора, формирует так называемое реляционное выражение или условие. Реляционные операторы можно рассматривать как частные случаи логических предикатов.

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

Равенство используется во многих конструкциях языков программирования и типах данных. Оно применяется для проверки наличия элемента в наборе или для доступа к значению по ключу. Оно используется в операторах `switch` для перенаправления потока управления в нужную ветвь, а также в процессе унификации в логическом программировании. Одно из возможных определений равенства заключается в том, что "если a равно b, то a и b могут использоваться взаимозаменяемо в любом контексте без каких-либо различий". Однако это утверждение не всегда справедливо, особенно при учёте изменяемости объектов в сочетании с равенством по содержимому.

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

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

Заказ

Сравнение нечисловых данных на большее или меньшее выполняется в соответствии с соглашением о сортировке (например, для текстовых строк – в лексикографическом порядке), которое может быть встроено в язык программирования и/или настраиваться программистом. Если требуется связать числовое значение с результатом сравнения двух элементов данных, скажем, a и b, обычно используется следующее соглашение: присваивается −1, если a < b, 0, если a = b, и 1, если a > b. Например, функция strcmp в языке C выполняет трехстороннее сравнение и возвращает −1, 0 или 1 в соответствии с этим соглашением, а функция qsort ожидает, что функция сравнения будет возвращать значения в соответствии с этим соглашением. В алгоритмах сортировки эффективность кода сравнения критически важна, поскольку является одним из основных факторов, влияющих на производительность сортировки. Сравнение пользовательских типов данных (типов данных, для которых язык программирования не имеет встроенной поддержки) может выполняться с помощью пользовательских или библиотечных функций (например, strcmp, упомянутой выше), или, в некоторых языках, путем перегрузки оператора сравнения – то есть присвоения оператору сравнения значения, определенного программистом, которое зависит от сравниваемых типов данных. Другой вариант – использование соглашения, например, покомпонентного сравнения.

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

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

Это требует, чтобы область была хорошо упорядочена.

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

Наиболее распространенные числовые реляционные операторы, используемые в языках программирования, приведены ниже. Стандартный SQL использует те же операторы, что и BASIC, в то время как многие базы данных допускают != в дополнение к <> из стандарта. SQL следует строгой булевой алгебре, т.е. не использует оценку короткого замыкания, которая является общей для большинства языков ниже. Например, PHP имеет ее, но в остальном он имеет те же два оператора, определенных как псевдонимы, как и многие базы данных SQL.

+ Общие реляционные операторы

| Конвенция | равна | не равна | больше чем | меньше чем | больше чем или равна | меньше чем или равна |
|---|---|---|---|---|---|---|
| В печати | = | ≠ | > | < | ≥ | ≤ |
| FORTRAN | EQ. | NE. | GT. | LT. | GE. | LE. |
| ALGOL 68 | = | ≠ | > | < | ≥ | ≤ |
| APL | = | ≠ | > | < | ≥ | ≤ |
| BASIC, ML, Pascal | = | <> | > | < | >= | <= |
| C like | == | != | > | < | >= | <= |
| MUMPS | = | '= | > | < | '<' | '>' |
| Lua | == | ~= | > | < | >= | <= |
| Erlang | == | /= | > | < | >= | <= |
| Bourne like shells | eq | ne | gt | lt | ge | le |
| Batch file | EQU | NEQ | GTR | LSS | GEQ | LEQ |
| MATLAB | == | ~= | > | < | >= | <= | eq(x,y) | ne(x,y) | gt(x,y) | lt(x,y) | ge(x,y) | le(x,y) |
| Fortran 90, Haskell | == | /= | > | < | >= | <= |
| Mathematica | == | != | > | < | >= | <= | Equal[x,y] | Unequal[x,y] | Greater[x,y] | Less[x,y] | GreaterEqual[x,y] | LessEqual[x,y] |

Другие соглашения встречаются реже: Common Lisp и Macsyma/Maxima используют операторы, подобные BASIC, за исключением неравенства, которое в Common Lisp обозначается /=, а в Macsyma/Maxima – #. В более старых Lisps использовались equal, greaterp и lessp, а для остальных операторов применялось отрицание с помощью not.

Обустройство оператора

В математике обычной практикой является последовательное использование реляционных операторов, например, в выражении 3 < x < y < 20 (что означает 3 < x и x < y и y < 20). Синтаксис понятен, поскольку эти реляционные операторы в математике обладают свойством транзитивности. Однако многие современные языки программирования интерпретируют выражение типа 3 < x < y как состоящее из двух левых (или правых) ассоциативных операторов, понимая его как (3 < x) < y. Если, например, x = 4, то получится (3 < 4) < y, и результатом вычисления будет `true < y`, что обычно лишено смысла. Тем не менее, это выражение компилируется в C/C++ и некоторых других языках, выдавая неожиданный результат (поскольку `true` здесь представляется числом 1). Возможно придать выражению x < y < z его привычное математическое значение, и некоторые языки программирования, такие как Python и Raku, поступают именно так. Другие, например, C# и Java, этого не делают, отчасти потому, что это противоречило бы принципу работы большинства других инфиксных операторов в языках, подобных C. Язык программирования D также не поддерживает такую интерпретацию, поскольку сохраняет некоторую совместимость с C, и, как отмечается, "разрешение выражений C, но с незначительно отличающейся семантикой (хотя, возможно, и в правильном направлении) привело бы к большей путанице, чем к удобству". Некоторые языки, такие как Common Lisp, используют для этого предикаты с несколькими аргументами. В Lisp выражение (<= 1 x 10) возвращает `true`, когда x находится в диапазоне от 1 до 10.

Смешанность с операторами назначения

Ранний FORTRAN (1956–57) был ограничен крайне ограниченными наборами символов, где = был единственным доступным реляционным оператором. Символов < или > не было (и, тем более, ≤ или ≥). Это вынудило разработчиков определять такие символы, как GT., LT., GE., EQ. и т.д., и впоследствии сделало соблазнительным использовать оставшийся символ = для присваивания, несмотря на явное противоречие математической практике (X=X+1 должно быть недопустимо). Международный алгебраический язык (IAL, ALGOL 58) и ALGOL (1958 и 1960) ввели оператор := для присваивания, оставив стандартный символ = для обозначения равенства, что стало общепринятой практикой в языках CPL, ALGOL W, ALGOL 68, Basic Combined Programming Language (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. В процессе, который описывали как "упрощение", операторы `and` и `or` в BCPL были заменены на `&` и `|` (которые впоследствии стали `&&` и `||` соответственно). В том же процессе стиль ALGOL `:=` в BCPL был заменен на `=` в B. Причина этого остается неизвестной. Поскольку в B не было специального синтаксиса для обновления переменных (например, `let` или подобного) и обновления разрешались в выражениях, это нестандартное значение знака равенства означало, что традиционная семантика знака равенства должна была быть связана с другим символом. Кен Томпсон использовал для этого ad hoc комбинацию `==`. После того, как была введена небольшая система типов, B превратился в C. Популярность этого языка и его связь с Unix привели к тому, что Java, C# и многие другие языки последовали его примеру синтаксически, несмотря на этот ненужный конфликт с математическим значением знака равенства.