Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

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

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

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

Равенство [ править ]

Использование [ править ]

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

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

Равенство местоположения и равенство контента [ править ]

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

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

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

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

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

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

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

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

В JavaScript , PHP , VBScript и некоторых других языках с динамической типизацией стандартный оператор равенства принимает значение true, если два значения равны, даже если они имеют разные типы, в результате чего число 4 сравнивается с текстовой строкой «4», например . В таких языках часто доступен типизированный оператор равенства, возвращающий истину только для значений с идентичными или эквивалентными типами (в PHP 4 === "4"это ложь, хотя 4 == "4"и истинно). [1] [2] Для языков, в которых число 0 может интерпретироваться как ложное , этот оператор может упростить такие вещи, как проверка нуля (как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 :

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

Стандартные реляционные операторы [ править ]

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

  1. ^ Включая FORTRAN II, III, IV, 66 и 77.
  2. ^ АЛГОЛ 68 :режимы строчки используются в коде на платформах с ограниченными наборами символов ( например , использование>=илиGEвместо), платформах безbold выделения (использование'ge') или платформах только с ЗАГЛАВНЫМИ буквами (используйте.GE или 'GE' ).
  3. ^ Включая ALGOL , Simula , Modula-2 , Eiffel , SQL , формулы электронных таблиц и другие.
  4. ^ В том числе C , C ++ , C # , Go , Java , JavaScript , Perl (только численное сравнение), PHP , Python , Руби , и R .
  5. ^ Включая оболочку Bourne , Bash , KornShell и Windows PowerShell . Символы<и>обычно используются в оболочке для перенаправления , поэтому необходимо использовать другие символы. Без дефиса используется в Perl для сравнения строк.
  6. ^ MATLAB, хотя в других отношениях использует аналогичный синтаксис как C, не использует!=, поскольку!в MATLAB отправляет следующий текст как командную строку в операционную систему . Первая форма также используется в Smalltalk , за исключением равенства, которым является=.
  7. ^ Включая FORTRAN 95, 2003, 2008 и 2015.

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

Синтаксис [ править ]

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

если  x  <  y :  print ( «x меньше y в этом примере» )

Другие языки программирования, такие как Lisp , используют префиксную нотацию , как показано ниже:

( > =  X  Y )

Цепочка операторов [ править ]

В математике, обычная практика цепи реляционных операторов, например, в 3 <х <у <20 ( что означает 3 <х и х <у и у <20). Синтаксис ясен, поскольку эти реляционные операторы в математике транзитивны.

Однако многие современные языки программирования увидят выражение типа 3 <x <y как состоящее из двух левых (или правых) ассоциативных операторов, интерпретируя его как нечто вроде (3 < x) < y. Если мы скажем, что x = 4, мы получим (3 < 4) < y, и оценка даст, true < yчто обычно не имеет смысла. Тем не менее, он компилируется на C / C ++ и некоторых других языках, что дает удивительный результат (поскольку истина здесь представлена ​​цифрой 1).

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

Некоторые языки, например 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 ),Оберон , Дилан , язык описания оборудования VHSIC ( VHDL ) и несколько других языков.

B и C [ править ]

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

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

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

Языки [ править ]

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

 int  x  =  1 ;  int  y  =  2 ;  if  ( x  =  y )  {  / * Этот код всегда будет выполняться, если y не равно 0 * /  printf ( "x равно% d, а y равно% 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 )  {  / * Ошибочное использование = versus == будет ошибкой времени компиляции * /  }

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

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

  1. ^ Заявка на патент: 14 мая 2003 г. в США заявка 20 040 230 959  «НЕ ОПЕРАТОР» была подана дляISNOTоператора сотрудниками Microsoft . Этот патент был выдан 18 ноября 2004 г.

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

См. Также [ править ]

  • Бинарное отношение
  • Обозначение общего оператора
  • Условный (компьютерное программирование)
  • Равенство (математика)
  • Знак равенства
  • Логический оператор
  • Операция (математика)
  • Оператор (математика)
  • Оператор (компьютерное программирование)
  • Оператор космического корабля
  • Тройственное отношение

Примечания и ссылки [ править ]

  1. ^ Авторы . «Сравнение объектов» . Руководство по PHP . Группа PHP . Проверено 29 июня 2014 года .
  2. ^ «PHP: Операторы сравнения - Руководство» . Проверено 31 июля 2008 года .
  3. ^ Реляционные и логические операторы из Mathematica
  4. Александреску, Андрей. D язык программирования . Эддисон Уэсли. п. 58. ISBN 978-0-321-63536-5.
  5. ^ Используется не только в АЛГОЛ-подобных языках, но также в ФОРТРАНЕ и БЕЙСИКЕ.
  6. ^ Поскольку некоторые программисты были сбиты с толку двойным значением (побитовый оператор и логическая связка) этих новых символов (согласно Деннису Ричи ). Только побитовое значение & и | были сохранены.
  7. ^ Хотя Деннис Ричи предположил, что это могло быть связано с «экономией на вводе текста», поскольку обновления переменных могут происходить чаще, чем сравнения в определенных типах программ.
  8. ^ Нулевое скалярное значение интерпретируется как ложное, а любое ненулевое скалярное значение интерпретируется как истинное; это обычно используется с целочисленными типами, подобноидиомам языка ассемблера .
  9. ^ Брайан Керниган и Деннис Ричи (1988) [1978]. Язык программирования C (второе изд.). Прентис Холл., 19