Реляционные операторы в программировании: сравнение, равенство, неравенство. Возвращают true/false или 0/1 в разных языках. Основы синтаксиса и условия.
Сравнивайте с английским: нажмите на абзац — оригинал откроется в окне. Кнопка EN под абзацем показывает его прямо в тексте.
Содержание
Введение
Конструкция языка программирования
Programming language construct
В информатике реляционный оператор — это конструкция или оператор языка программирования, который проверяет или определяет определенное отношение между двумя сущностями. К ним относятся равенство (например, ==) и неравенство (например, 4 ≥ 3). В языках программирования, которые включают в свою систему типов отдельный булев тип данных, таких как Паскаль, Ада или Java, эти операторы обычно возвращают значение "истина" или "ложь" в зависимости от того, выполняется ли заданное отношение между двумя операндами. В языках, таких как C, реляционные операторы возвращают целые числа 0 или 1, где 0 представляет "ложь", а любое ненулевое значение представляет "истину". Выражение, созданное с использованием реляционного оператора, формирует так называемое реляционное выражение или условие. Реляционные операторы можно рассматривать как частные случаи логических предикатов.
In computer science, a relational operator is a programming language construct or operator that tests or defines some kind of relation between two entities. These include numerical equality (e. g., ) and inequalities (e. g., 4 ≥ 3). In programming languages that include a distinct boolean data type in their type system, like Pascal, Ada, or Java, these operators usually evaluate to true or false, depending on if the conditional relationship between the two operands holds or not. In languages such as C, relational operators return the integers 0 or 1, where 0 stands for false and any non zero value stands for true. An expression created using a relational operator forms what is termed a relational expression or a condition. Relational operators can be seen as special cases of logical predicates.
Использование
Равенство используется во многих конструкциях языков программирования и типах данных. Оно применяется для проверки наличия элемента в наборе или для доступа к значению по ключу. Оно используется в операторах `switch` для перенаправления потока управления в нужную ветвь, а также в процессе унификации в логическом программировании. Одно из возможных определений равенства заключается в том, что "если a равно b, то a и b могут использоваться взаимозаменяемо в любом контексте без каких-либо различий". Однако это утверждение не всегда справедливо, особенно при учёте изменяемости объектов в сочетании с равенством по содержимому.
Equality is used in many programming language constructs and data types. It is used to test if an element already exists in a set, or to access to a value through a key. It is used in switch statements to dispatch the control flow to the correct branch, and during the unification process in logic programming. One possible meaning of equality is that "if a equals b, then either a or b can be used interchangeably in any context without noticing any difference." But this statement does not necessarily hold, particularly when taking into account mutability together with content equality.
Сравнение значений различных типов
В JavaScript, PHP, VBScript и нескольких других языках с динамической типизацией стандартный оператор равенства возвращает true, если два значения равны, даже если они имеют разные типы, например, число 4 будет считаться равным текстовой строке "4". В таких языках часто также доступен оператор строгого равенства, который возвращает true только для значений с идентичными типами или типами, которые могут быть неявно преобразованы (в PHP, 4 === "4" будет false, хотя 4 == "4" будет true). Для языков, где число 0 может интерпретироваться как false, этот оператор может упростить проверку на ноль (так как x == 0 будет true, если x равно либо 0, либо "0" при использовании оператора равенства, не учитывающего тип).
In JavaScript, PHP, VBScript and a few other dynamically typed languages, the standard equality operator evaluates to true if two values are equal, even if they have different types, making the number 4 compare equal to the text string "4", for instance. A typed equality operator is often available also, in such languages, returning true only for values with identical or equivalent types (in PHP, 4 === "4" is false although 4 == "4" is true). For languages where the number 0 may be interpreted as false, this operator may simplify things such as checking for zero (as x == 0 would be true for x being either 0 or "0" using the type agnostic equality operator).
Заказ
Сравнение нечисловых данных на большее или меньшее выполняется в соответствии с соглашением о сортировке (например, для текстовых строк – в лексикографическом порядке), которое может быть встроено в язык программирования и/или настраиваться программистом. Если требуется связать числовое значение с результатом сравнения двух элементов данных, скажем, a и b, обычно используется следующее соглашение: присваивается −1, если a < b, 0, если a = b, и 1, если a > b. Например, функция strcmp в языке C выполняет трехстороннее сравнение и возвращает −1, 0 или 1 в соответствии с этим соглашением, а функция qsort ожидает, что функция сравнения будет возвращать значения в соответствии с этим соглашением. В алгоритмах сортировки эффективность кода сравнения критически важна, поскольку является одним из основных факторов, влияющих на производительность сортировки. Сравнение пользовательских типов данных (типов данных, для которых язык программирования не имеет встроенной поддержки) может выполняться с помощью пользовательских или библиотечных функций (например, strcmp, упомянутой выше), или, в некоторых языках, путем перегрузки оператора сравнения – то есть присвоения оператору сравнения значения, определенного программистом, которое зависит от сравниваемых типов данных. Другой вариант – использование соглашения, например, покомпонентного сравнения.
Greater than and less than comparison of non numeric data is performed according to a sort convention (such as, for text strings, lexicographical order) which may be built into the programming language and/or configurable by a programmer. When it is desired to associate a numeric value with the result of a comparison between two data items, say a and b, the usual convention is to assign −1 if a < b, 0 if a = b and 1 if a > b. For example, the C function strcmp performs a three way comparison and returns −1, 0, or 1 according to this convention, and qsort expects the comparison function to return values according to this convention. In sorting algorithms, the efficiency of comparison code is critical since it is one of the major factors contributing to sorting performance. Comparison of programmer defined data types (data types for which the programming language has no in built understanding) may be carried out by custom written or library functions (such as strcmp mentioned above), or, in some languages, by overloading a comparison operator – that is, assigning a programmer defined meaning that depends on the data types being compared. Another alternative is using some convention such as member wise comparison.
Логическая эквивалентность
Хотя это может быть не сразу очевидно, как булевы логические операторы XOR, AND, OR и NOT, реляционные операторы могут быть сконструированы таким образом, чтобы быть логически эквивалентными, то есть все они могут быть определены через один другой. Следующие четыре условных выражения имеют одну и ту же логическую эквивалентность E (либо все истинны, либо все ложны) для любых заданных значений x и y:
Though perhaps unobvious at first, like the boolean logical operators XOR, AND, OR, and NOT, relational operators can be designed to have logical equivalence, such that they can all be defined in terms of one another. The following four conditional statements all have the same logical equivalence E (either all true or all false) for any given x and y values:
Это требует, чтобы область была хорошо упорядочена.
This relies on the domain being well ordered.
Стандартные реляционные операторы
Наиболее распространенные числовые реляционные операторы, используемые в языках программирования, приведены ниже. Стандартный SQL использует те же операторы, что и BASIC, в то время как многие базы данных допускают != в дополнение к <> из стандарта. SQL следует строгой булевой алгебре, т.е. не использует оценку короткого замыкания, которая является общей для большинства языков ниже. Например, PHP имеет ее, но в остальном он имеет те же два оператора, определенных как псевдонимы, как и многие базы данных SQL.
The most common numerical relational operators used in programming languages are shown below. Standard SQL uses the same operators as BASIC, while many databases allow != in addition to <> from the standard. SQL follows strict boolean algebra, i. e. doesn't use short circuit evaluation, which is common to most languages below. E. g. PHP has it, but otherwise it has these same two operators defined as aliases, like many SQL databases. + Common relational operators Convention equal to not equal to greater than less than greater thanor equal to less thanor equal to In print = ≠ > < ≥ ≤ FORTRAN EQ. NE. GT. LT. GE. LE. ALGOL 68 = ≠ > < ≥ ≤ /= >= <= eq ne gt lt ge le 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 LEQMATLAB == ~= > < >= <= 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]
Other conventions are less common: Common Lisp and Macsyma/Maxima use Basic like operators except for inequality, which is /= in Common Lisp and # in Macsyma/Maxima. Older Lisps used equal, greaterp, and lessp; and negated them using not for the remaining operators.
+ Общие реляционные операторы
The most common numerical relational operators used in programming languages are shown below. Standard SQL uses the same operators as BASIC, while many databases allow != in addition to <> from the standard. SQL follows strict boolean algebra, i. e. doesn't use short circuit evaluation, which is common to most languages below. E. g. PHP has it, but otherwise it has these same two operators defined as aliases, like many SQL databases. + Common relational operators Convention equal to not equal to greater than less than greater thanor equal to less thanor equal to In print = ≠ > < ≥ ≤ FORTRAN EQ. NE. GT. LT. GE. LE. ALGOL 68 = ≠ > < ≥ ≤ /= >= <= eq ne gt lt ge le 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 LEQMATLAB == ~= > < >= <= 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]
Other conventions are less common: Common Lisp and Macsyma/Maxima use Basic like operators except for inequality, which is /= in Common Lisp and # in Macsyma/Maxima. Older Lisps used equal, greaterp, and lessp; and negated them using not for the remaining operators.
The most common numerical relational operators used in programming languages are shown below. Standard SQL uses the same operators as BASIC, while many databases allow != in addition to <> from the standard. SQL follows strict boolean algebra, i. e. doesn't use short circuit evaluation, which is common to most languages below. E. g. PHP has it, but otherwise it has these same two operators defined as aliases, like many SQL databases. + Common relational operators Convention equal to not equal to greater than less than greater thanor equal to less thanor equal to In print = ≠ > < ≥ ≤ FORTRAN EQ. NE. GT. LT. GE. LE. ALGOL 68 = ≠ > < ≥ ≤ /= >= <= eq ne gt lt ge le 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 LEQMATLAB == ~= > < >= <= 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]
Other conventions are less common: Common Lisp and Macsyma/Maxima use Basic like operators except for inequality, which is /= in Common Lisp and # in Macsyma/Maxima. Older Lisps used equal, greaterp, and lessp; and negated them using not for the remaining operators.
Другие соглашения встречаются реже: Common Lisp и Macsyma/Maxima используют операторы, подобные BASIC, за исключением неравенства, которое в Common Lisp обозначается /=, а в Macsyma/Maxima – #. В более старых Lisps использовались equal, greaterp и lessp, а для остальных операторов применялось отрицание с помощью not.
The most common numerical relational operators used in programming languages are shown below. Standard SQL uses the same operators as BASIC, while many databases allow != in addition to <> from the standard. SQL follows strict boolean algebra, i. e. doesn't use short circuit evaluation, which is common to most languages below. E. g. PHP has it, but otherwise it has these same two operators defined as aliases, like many SQL databases. + Common relational operators Convention equal to not equal to greater than less than greater thanor equal to less thanor equal to In print = ≠ > < ≥ ≤ FORTRAN EQ. NE. GT. LT. GE. LE. ALGOL 68 = ≠ > < ≥ ≤ /= >= <= eq ne gt lt ge le 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 LEQMATLAB == ~= > < >= <= 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]
Other conventions are less common: Common Lisp and Macsyma/Maxima use Basic like operators except for inequality, which is /= in Common Lisp and # in Macsyma/Maxima. Older Lisps used equal, greaterp, and lessp; and negated them using not for the remaining operators.
Обустройство оператора
В математике обычной практикой является последовательное использование реляционных операторов, например, в выражении 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.
In mathematics, it is common practice to chain relational operators, such as in 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. However, many recent programming languages would see an expression like 3 < x < y as consisting of two left (or right ) associative operators, interpreting it as something like (3 < x) < y. If we say that x=4, we then get (3 < 4) < y, and evaluation will give true < y which generally does not make sense. However, it does compile in C/C++ and some other languages, yielding surprising result (as true would be represented by the number 1 here). It is possible to give the expression x < y < z its familiar mathematical meaning, and some programming languages such as Python and Raku do that. Others, such as C# and Java, do not, partly because it would differ from the way most other infix operators work in C like languages. The D programming language does not do that since it maintains some compatibility with C, and "Allowing C expressions but with subtly different semantics (albeit arguably in the right direction) would add more confusion than convenience". Some languages, like Common Lisp, use multiple argument predicates for this. In Lisp (<= 1 x 10) is true when x is between 1 and 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) и многих других языках.
Early FORTRAN (1956–57) was bounded by heavily restricted character sets where = was the only relational operator available. There were no < or > (and certainly no ≤ or ≥). This forced the designers to define symbols such as GT., LT., GE., EQ. etc. and subsequently made it tempting to use the remaining = character for copying, despite the obvious incoherence with mathematical usage (X=X+1 should be impossible). International Algebraic Language (IAL, ALGOL 58) and ALGOL (1958 and 1960) thus introduced := for assignment, leaving the standard = available for equality, a convention followed by 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), and several other languages.
B и C
Этот единый де-факто стандарт среди большинства языков программирования в конечном итоге был косвенно изменен минималистическим компилируемым языком под названием B. Его единственное предполагаемое применение заключалось в качестве средства для первой портировки (тогда ещё очень примитивного) Unix, но он также эволюционировал в весьма влиятельный язык C. Язык B возник как синтаксически измененный вариант языка системного программирования BCPL, упрощенной (и нетипизированной) версии CPL. В процессе, который описывали как "упрощение", операторы `and` и `or` в BCPL были заменены на `&` и `|` (которые впоследствии стали `&&` и `||` соответственно). В том же процессе стиль ALGOL `:=` в BCPL был заменен на `=` в B. Причина этого остается неизвестной. Поскольку в B не было специального синтаксиса для обновления переменных (например, `let` или подобного) и обновления разрешались в выражениях, это нестандартное значение знака равенства означало, что традиционная семантика знака равенства должна была быть связана с другим символом. Кен Томпсон использовал для этого ad hoc комбинацию `==`. После того, как была введена небольшая система типов, B превратился в C. Популярность этого языка и его связь с Unix привели к тому, что Java, C# и многие другие языки последовали его примеру синтаксически, несмотря на этот ненужный конфликт с математическим значением знака равенства.
This uniform de facto standard among most programming languages was eventually changed, indirectly, by a minimalist compiled language named B. Its sole intended application was as a vehicle for a first port of (a then very primitive) Unix, but it also evolved into the very influential C language. B started off as a syntactically changed variant of the systems programming language BCPL, a simplified (and typeless) version of CPL. In what has been described as a "strip down" process, the and and or operators of BCPL were replaced with & and | (which would later become && and ||, respectively.). In the same process, the ALGOL style := of BCPL was replaced by = in B. The reason for all this being unknown. As variable updates had no special syntax in B (such as let or similar) and were allowed in expressions, this non standard meaning of the equal sign meant that the traditional semantics of the equal sign now had to be associated with another symbol. Ken Thompson used the ad hoc == combination for this. As a small type system was later introduced, B then became C. The popularity of this language along with its association with Unix, led to Java, C#, and many other languages following suit, syntactically, despite this needless conflict with the mathematical meaning of the equal sign.