Реляционный оператор
Эта статья нуждается в дополнительных цитатах для проверки . ( март 2022 г. ) |
В информатике — реляционный оператор это языка программирования конструкция или оператор , который проверяет или определяет некоторый вид связи между двумя объектами . К ним относятся числовое равенство ( например , 5 = 5 ) и неравенства ( например , 4 ≥ 3 ).
отдельный логический тип данных В языках программирования, которые включают в свою систему типов , таких как Pascal , Ada или Java , эти операторы обычно оцениваются как true или false, в зависимости от того, сохраняется или нет условная связь между двумя операндами . В таких языках, как C , реляционные операторы возвращают целые числа 0 или 1, где 0 означает ложь, а любое ненулевое значение означает истину.
Выражение , созданное с помощью оператора отношения, образует то, что называется выражением отношения или условием . Операторы отношения можно рассматривать как частные случаи логических предикатов .
Равенство
[ редактировать ]Использование
[ редактировать ]Равенство используется во многих конструкциях и типах данных языка программирования. Он используется для проверки наличия элемента в наборе или для доступа к значению через ключ. Он используется в операторах переключения для направления потока управления в правильную ветвь, а также во время процесса унификации в логическом программировании.
Может существовать несколько допустимых определений равенства, и любой конкретный язык может использовать одно или несколько из них, в зависимости от различных аспектов проектирования. Одно из возможных значений равенства состоит в том, что «если a равно b , то либо a , либо b можно использовать взаимозаменяемо в любом контексте, не замечая никакой разницы». Но это утверждение не обязательно справедливо, особенно если принять во внимание изменчивость вместе с равенством содержания.
Равенство местоположения и равенство контента
[ редактировать ]Иногда, особенно в объектно-ориентированном программировании , сравнение поднимает вопросы о типах данных и наследовании , равенстве и идентичности . Часто необходимо различать:
- два разных объекта одного типа, например две руки
- два объекта равны, но различны, например, две банкноты по 10 долларов.
- два объекта равны, но имеют разное представление, например, купюра в 1 доллар и монета в 1 доллар.
- две разные ссылки на один и тот же объект, например, два прозвища одного и того же человека
Во многих современных языках программирования доступ к объектам и структурам данных осуществляется через ссылки . В таких языках возникает необходимость проверять два разных типа равенства:
- Равенство расположения (идентичность): если две ссылки (A и B) ссылаются на один и тот же объект. Взаимодействия с объектом через А неотличимы от таких же взаимодействий через Б, и в частности изменения объекта через А отражаются через Б.
- Равенство содержимого: если объекты, на которые ссылаются две ссылки (A и B), в некотором смысле эквивалентны:
- Структурное равенство (то есть их содержание одинаково). который может быть либо поверхностным (проверка только непосредственных частей), либо глубоким (рекурсивная проверка на равенство частей). Простой способ добиться этого — использовать репрезентативное равенство: проверять, что значения имеют одинаковое представление.
- Какое-то другое заказное равенство, сохраняющее внешнее поведение. Например, 1/2 и 2/4 считаются равными, если рассматривать их как рациональное число. Возможным требованием может быть то, что «A = B тогда и только тогда, когда все операции над объектами A и B будут иметь одинаковый результат», в дополнение к рефлексивности , симметрии и транзитивности .
Первый тип равенства обычно подразумевает второй (за исключением таких вещей, как не число ( NaN ), которые не равны самому себе), но обратное не обязательно верно. Например, два строковых объекта могут быть разными объектами (неравными в первом смысле), но содержать одну и ту же последовательность символов (равными во втором смысле). см . в разделе «Идентификация» Дополнительную информацию об этой проблеме .
Действительные числа, включая многие простые дроби , не могут быть точно представлены в арифметике с плавающей запятой , и может потребоваться проверка равенства в пределах заданного допуска. Такая толерантность, однако, может легко нарушить желаемые свойства, такие как транзитивность, тогда как рефлексивность тоже нарушается: стандарт IEEE для чисел с плавающей запятой требует, чтобы NaN ≠ NaN выполнялось. Напротив, частный стандарт (2022 г.) для posit -арифметики (сторонники posit подразумевают замену чисел с плавающей запятой IEEE) имеет аналогичную концепцию NaR (Not a Real), где NaR = NaR . выполняется [1]
Другие элементы программирования, такие как вычислимые функции, могут либо не иметь смысла равенства, либо иметь невычислимое равенство. По этим причинам некоторые языки определяют явное понятие «сопоставимого» в форме базового класса, интерфейса, признака или протокола, который используется либо явно, путем объявления в исходном коде, либо неявно, через структуру соответствующего типа.
Сравнение значений разных типов
[ редактировать ]В JavaScript , PHP , VBScript и некоторых других динамически типизированных языках стандартный оператор равенства следует так называемой свободной типизации , то есть он оценивается как true, даже если два значения не равны и относятся к несовместимым типам, но может быть приведен к каждому из них . другой - по некоторому набору правил, специфичных для языка, например, сравнивая число 4 с текстовой строкой "4". Хотя такое поведение обычно предназначено для упрощения языка, оно может привести к неожиданным и трудно предсказуемым последствиям, о которых многие программисты не подозревают. Например, нестрогие правила равенства в Javascript могут привести к тому, что равенство будет непереходным (т. a == b
и b == c
, но a != c
), или сделать определенные значения равными их собственному отрицанию. [2]
В этих языках также часто доступен оператор строгого равенства, возвращающий true только для значений с идентичными или эквивалентными типами (в PHP 4 === "4"
неверно, хотя 4 == "4"
это правда). [3] [4] Для языков, где число 0 может интерпретироваться как false , этот оператор может упростить такие вещи, как проверка нуля (например, x == 0
было бы верно для x, равного 0 или «0» с использованием независимого от типа оператора равенства).
Заказ
[ редактировать ]«больше» и «меньше» Сравнение нечисловых данных выполняется в соответствии с соглашением о сортировке (например, для текстовых строк — лексикографическим порядком ), которое может быть встроено в язык программирования и/или настраивать программистом.
Когда требуется связать числовое значение с результатом сравнения двух элементов данных, скажем, a и b , обычное соглашение состоит в том, чтобы присвоить -1, если a < b, 0, если a = b, и 1, если a > b. Например, функция C strcmp
выполняет трехстороннее сравнение и возвращает -1, 0 или 1 в соответствии с этим соглашением, а qsort ожидает, что функция сравнения вернет значения в соответствии с этим соглашением. В алгоритмах сортировки эффективность кода сравнения имеет решающее значение, поскольку она является одним из основных факторов, влияющих на производительность сортировки.
Сравнение типов данных , определяемых программистом (типов данных, для которых язык программирования не имеет встроенного понимания) может выполняться с помощью специально написанных или библиотечных функций (таких как strcmp
упоминалось выше), или, в некоторых языках, путем перегрузки оператора сравнения, то есть присвоения определенного программистом значения, которое зависит от сравниваемых типов данных. Другой альтернативой является использование некоторого соглашения, такого как сравнение элементов.
Логическая эквивалентность
[ редактировать ]Хотя на первый взгляд это может быть и неочевидно, подобно логическим операторам XOR, AND, OR и NOT, реляционные операторы могут быть спроектированы так, чтобы иметь логическую эквивалентность , так что все они могут быть определены в терминах друг друга. Следующие четыре условных утверждения имеют одинаковую логическую эквивалентность E (либо все истинны, либо все ложны) для любых заданных значений x и y :
домен Это зависит от того, насколько хорошо упорядочен .
Стандартные операторы отношений
[ редактировать ]Ниже показаны наиболее распространенные числовые операторы отношения, используемые в языках программирования. Стандартный SQL использует те же операторы, что и BASIC, тогда как многие базы данных позволяют !=
в дополнение к <>
от стандарта. SQL следует строгой логической алгебре , т.е. не использует сокращенную оценку , которая является общей для большинства языков, описанных ниже. Например, в PHP он есть, но в остальном эти же два оператора определены как псевдонимы, как и во многих базах данных SQL.
Соглашение | равный | не равен | больше, чем | меньше, чем | больше, чем или равно |
меньше, чем или равно |
---|---|---|---|---|---|---|
В печати | = | ≠ | > | < | ≥ | ≤ |
ФОРТРАН [примечание 1] | .EQ.
|
.NE.
|
.GT.
|
.LT.
|
.GE.
|
.LE.
|
АЛГОЛ 68 [примечание 2] | =
|
≠
|
>
|
<
|
≥
|
≤
|
/=
|
>=
|
<=
| ||||
eq
|
ne
|
gt
|
lt
|
ge
|
le
| |
АПЛ | =
|
≠
|
>
|
<
|
≥
|
≤
|
БЕЙСИК , МЛ , Паскаль [примечание 3] | =
|
<> [примечание 4]
|
>
|
<
|
>=
|
<=
|
C-подобный [примечание 5] | ==
|
!=
|
>
|
<
|
>=
|
<=
|
Свинка | =
|
'=
|
>
|
<
|
'<
|
'>
|
Два | ==
|
~=
|
>
|
<
|
>=
|
<=
|
Эрланг | ==
|
/=
|
>
|
<
|
>=
|
=<
|
=:=
|
=/=
| |||||
типа Борна Раковины [примечание 6] | -eq
|
-ne
|
-gt
|
-lt
|
-ge
|
-le
|
Пакетный файл | EQU
|
NEQ
|
GTR
|
LSS
|
GEQ
|
LEQ
|
МАТЛАБ [примечание 7] | ==
|
~=
|
>
|
<
|
>=
|
<=
|
eq(x,y)
|
ne(x,y)
|
gt(x,y)
|
lt(x,y)
|
ge(x,y)
|
le(x,y)
| |
Фортран 90 , [примечание 8] Хаскелл | ==
|
/=
|
>
|
<
|
>=
|
<=
|
Математика [5] | ==
|
!=
|
>
|
<
|
>=
|
<=
|
Equal[x,y]
|
Unequal[x,y]
|
Greater[x,y]
|
Less[x,y]
|
GreaterEqual[x,y]
|
LessEqual[x,y]
|
- ^ Включая ФОРТРАН II, III, IV, 66 и 77.
- ^ АЛГОЛ 68 : режимы ограничения используются в коде на платформах с ограниченными наборами символов ( например , используйте
>=
илиGE
вместо≥
), платформы безbold
акцент (используйте'ge'
) или платформы, в которых используются только ПРОПИСНЫЕ РЕГИСТРЫ (используйте.GE
или'GE'
). - ^ Включая ALGOL , Simula , Modula-2 , Eiffel , SQL , формулы электронных таблиц и другие.
- ^ Модуль-2 также распознает
#
- ^ Включая C , C++ , C# , Go , Java , JavaScript , Perl только численное сравнение), PHP , Python , Ruby и R. (
- ^ Включая оболочки Bourne , Bash , KornShell и Windows PowerShell . Символы
<
и>
обычно используются в оболочке для перенаправления , поэтому необходимо использовать другие символы. Без дефиса используется в Perl для сравнения строк. - ^ MATLAB, хотя в других отношениях использует синтаксис, аналогичный C, не использует
!=
, как!
в MATLAB отправляет следующий текст в виде командной строки в операционную систему . Первая форма также используется в Smalltalk , за исключением равенства, которое=
. - ^ Включая FORTRAN 95, 2003, 2008 и 2015 гг.
Другие соглашения менее распространены: Common Lisp и Macsyma / Maxima используют операторы, подобные Basic, для числовых значений, за исключением неравенства, которое /=
в Common Lisp и #
в Максиме/Максиме. Common Lisp имеет множество других наборов операторов равенства и отношений, служащих различным целям, в том числе eq
, eql
, equal
, equalp
, и string=
. [6] старый Лисп Используется equal
, greaterp
, и lessp
; и отрицал их, используя not
для остальных операторов.
Синтаксис
[ редактировать ]Операторы отношения также используются в технической литературе вместо слов. Операторы отношения обычно записываются в инфиксной записи , если это поддерживается языком программирования. Это означает, что они появляются между своими операндами (два связанных выражения). Например, выражение в Python выведет сообщение, если x меньше y :
if x < y:
print("x is less than y in this example")
Другие языки программирования, такие как Lisp , используют префиксную запись следующим образом:
(>= X Y)
Цепочка операторов
[ редактировать ]В математике общепринятой практикой является объединение операторов отношения в цепочку, например, 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, но с немного другой семантикой (хотя, возможно, в правильном направлении), добавило бы больше путаницы, чем удобства». [7]
Некоторые языки, такие как Common Lisp , используют для этого предикаты с несколькими аргументами. В Лиспе (<= 1 x 10)
истинно, когда x находится между 1 и 10.
Путаница с операторами присваивания
[ редактировать ]Ранний ФОРТРАН (1956–57) был ограничен сильно ограниченными наборами символов, где =
был единственным доступным реляционным оператором. Не было <
или >
(и конечно нет ≤
или ≥
). Это заставило дизайнеров определить такие символы, как .GT.
, .LT.
, .GE.
, .EQ.
и т. д., что впоследствии вызвало соблазн использовать оставшиеся =
символ для копирования, несмотря на очевидную несогласованность с математическим использованием ( X=X+1
должно быть невозможно).
Таким образом были представлены Международный алгебраический язык (IAL, ALGOL 58 ) и ALGOL (1958 и 1960). :=
по заданию, оставляя стандарт =
доступно для равенства, соглашение, которому следуют CPL , ALGOL W , ALGOL 68 , базовый комбинированный язык программирования ( BCPL ), Simula , язык SET ( SETL ), Pascal , Smalltalk , Modula-2 , Ada , Standard ML , OCaml , Eiffel , Object Pascal ( Delphi ), Oberon , Dylan , язык описания оборудования VHSIC ( VHDL ) и несколько других языков.
Б и С
[ редактировать ]факто среди большинства языков программирования в конечном итоге был косвенно изменен минималистским компилируемым языком под названием B. Этот единый стандарт де - Его единственным предполагаемым применением было создание первого порта (тогда очень примитивного) Unix , но он также превратился в очень влиятельный C. язык
B начинался как синтаксически измененный вариант языка системного программирования BCPL , упрощенная (и бестиповая) версия CPL . В процессе, который был описан как процесс «разборки», and
и or
операторы BCPL [8] были заменены на &
и |
(который позже станет &&
и ||
, соответственно. [9] ). В том же процессе стиль АЛГОЛА :=
BCPL был заменен на =
в Б. Причина всего этого неизвестна. [10] Поскольку обновления переменных не имели специального синтаксиса в B (например, let
или подобные) и были разрешены в выражениях, это нестандартное значение знака равенства означало, что традиционная семантика знака равенства теперь должна была быть связана с другим символом. Кен Томпсон использовал специальную ==
комбинация для этого.
Поскольку позже была введена система малых типов, B затем стал C. Популярность этого языка вместе с его ассоциацией с Unix привела к тому, что Java, C# и многие другие языки последовали его синтаксическому примеру, несмотря на этот ненужный конфликт с математическим значением знак равенства.
Языки
[ редактировать ]Присваивания в C имеют значение , и поскольку любое ненулевое скалярное значение интерпретируется как истинное в условных выражениях , [11] код if (x = y)
является законным, но имеет совершенно иное значение, чем if (x == y)
. Первый фрагмент кода означает «присвойте y значению x , и если новое значение x не равно нулю, выполните следующий оператор». Последний фрагмент означает « если и только если x равно y , выполните следующий оператор». [12]
int x = 1;
int y = 2;
if (x = y) {
/* This code will always execute if y is anything but 0*/
printf("x is %d and y is %d\n", x, y);
}
Хотя в Java и C# используются те же операторы, что и в C, эта ошибка обычно приводит к ошибке компиляции в этих языках, поскольку условие if должно иметь тип boolean
, и не существует неявного способа преобразования других типов ( например , чисел) в boolean
с. Поэтому, если переменная, которой назначена, не имеет типа boolean
(или тип оболочки Boolean
), произойдет ошибка компиляции.
В АЛГОЛ-подобных языках, таких как Pascal, Delphi и Ada (в том смысле, что они допускают определения вложенных функций ), а также в Python и многих функциональных языках, среди прочих, операторы присваивания не могут появляться в выражениях (включая if
пунктов), тем самым исключая этот класс ошибок. Некоторые компиляторы, такие как GNU Compiler Collection (GCC), выдают предупреждение при компиляции кода, содержащего оператор присваивания внутри оператора if, хотя существуют некоторые законные варианты использования присваивания внутри условия if. В таких случаях присваивание должно быть явно заключено в дополнительную пару круглых скобок, чтобы избежать предупреждения.
Аналогично, некоторые языки, такие как BASIC, используют только =
символ присваивания и равенства, поскольку они синтаксически разделены (как и в Pascal, Ada, Python и т. д., операторы присваивания не могут появляться в выражениях).
Некоторые программисты имеют привычку писать сравнения с константой в порядке, обратном обычному:
if (2 == a) { /* Mistaken use of = versus == would be a compile-time error */
}
Если =
используется случайно, полученный код недействителен, поскольку 2 не является переменной. Компилятор выдаст сообщение об ошибке, в котором можно заменить соответствующий оператор. Этот стиль кодирования называется левым сравнением или условиями Йоды .
В этой таблице перечислены различные механизмы проверки этих двух типов равенства на разных языках:
Язык | Физическое равенство | Структурное равенство | Примечания |
---|---|---|---|
АЛГОЛ 68 | a :=: b или a is b |
a = b |
когда a и b являются указателями
|
С , С++ | a == b |
*a == *b |
когда a и b являются указателями
|
С# | object.ReferenceEquals(a, b) |
a.Equals(b) |
The == по умолчанию оператор ReferenceEquals , но может быть перегружен для выполнения Equals вместо.
|
Общий Лисп | (eq a b) |
(equal a b) |
|
Эрланг | a =:= b
|
a == b
|
когда a и b — числа |
Идти | a == b |
reflect.DeepEqual(*a, *b) |
когда a и b являются указателями |
Ява | a == b |
a.equals(b) |
|
JavaScript | a === b |
a == b |
когда a и b — два строковых объекта, содержащих эквивалентные символы, оператор === все равно вернет true. |
OCaml , Smalltalk | a == b |
a = b |
|
Паскаль | a^ = b^ |
a = b |
|
Перл | $a == $b |
$$a == $$b |
когда $a и $b являются ссылками на скаляры
|
PHP | $a === $b |
$a == $b |
когда $a и $b являются объектами
|
Питон | a is b |
a == b |
|
Руби | a.equal?(b) |
a == b |
|
Схема | (eq? a b) |
(equal? a b) |
|
Быстрый | a === b |
a == b |
когда a и b имеют тип класса |
Визуальный Бейсик .NET [неравенство 1] | a Is b или object.ReferenceEquals(a, b) |
a = b или a.Equals(b) |
То же, что С# |
Objective-C ( Какао , GNUstep ) | a == b |
[a isEqual:b] |
когда a и b являются указателями на объекты, которые являются экземплярами NSObject
|
- ^ Заявка на патент: 14 мая 2003 г., В США была подана заявка № 20 040 230 959 «НЕ ОПЕРАТОР».
ISNOT
оператор сотрудниками Microsoft . Этот патент был выдан 18 ноября 2004 г.
Руби использует a === b
означает, что «b является членом множества a», хотя детали того, что значит быть членом, значительно различаются в зависимости от задействованных типов данных. ===
здесь известен как оператор «равенства регистра» или «подбора регистра».
См. также
[ редактировать ]- Бинарное отношение
- Общие обозначения операторов
- Условное (компьютерное программирование)
- Равенство (математика)
- Знак равенства
- Логический оператор
- Операция (математика)
- Оператор (математика)
- Оператор (компьютерное программирование)
- Оператор космического корабля
- Триадное отношение
Примечания и ссылки
[ редактировать ]- ^ Стандарт для положительной арифметики (2022 г.)
- ^ Денис, Довгань. "ВТФДЖС" . Проверено 25 июля 2024 г.
- ^ Участники . «Сравнение предметов» . Руководство по PHP . Группа PHP . Проверено 29 июня 2014 г.
{{cite web}}
:|author=
имеет родовое имя ( помощь ) ; Внешняя ссылка в
( помощь )|author=
- ^ «PHP: Операторы сравнения — Руководство» . Проверено 31 июля 2008 г.
- ^ логические операторы Mathematica Реляционные и
- ^ «Почему существует так много способов сравнения на предмет равенства?» . Переполнение стека . Проверено 25 июля 2024 г.
- ^ Александреску, Андрей (2010). Язык программирования D. Эддисон Уэсли. п. 58. ИСБН 978-0-321-63536-5 .
- ^ Используется не только в языках, подобных АЛГОЛу, но также в FORTRAN и BASIC.
- ^ Поскольку некоторых программистов смутило двойное значение (побитовый оператор и логическая связка) этих новых символов (по мнению Денниса Ритчи ). Только побитовое значение & и | были сохранены.
- ^ Хотя Деннис Ритчи предположил, что это могло быть связано с «экономией набора текста», поскольку в определенных типах программ обновления переменных могут происходить чаще, чем сравнения.
- ^ Нулевое скалярное значение интерпретируется как ложное, а любое ненулевое скалярное значение интерпретируется как истинное; обычно это используется с целочисленными типами, подобно ассемблера . идиомам
- ^ Брайан Керниган и Деннис Ритчи (1988) [1978]. Язык программирования C (второе изд.). Прентис Холл. , 19