stringtranslate.com

Operador relacional

En informática , un operador relacional es una construcción u operador del lenguaje de programación que prueba o define algún tipo de relación entre dos entidades . Estas incluyen la igualdad numérica ( p. ej. , 5 = 5 ) y las desigualdades ( p. ej ., 4 ≥ 3 ).

En los lenguajes de programación que incluyen un tipo de datos booleano distinto en su sistema de tipos , como Pascal , Ada o Java , estos operadores suelen evaluarse como verdaderos o falsos, dependiendo de si la relación condicional entre los dos operandos se cumple o no. En lenguajes como C , los operadores relacionales devuelven los números enteros 0 o 1, donde 0 representa falso y cualquier valor distinto de cero representa verdadero.

Una expresión creada mediante un operador relacional forma lo que se denomina una expresión relacional o una condición . Los operadores relacionales pueden considerarse casos especiales de predicados lógicos .

Igualdad

Uso

La igualdad se utiliza en muchos lenguajes de programación y tipos de datos. Se utiliza para comprobar si un elemento ya existe en un conjunto o para acceder a un valor mediante una clave. Se utiliza en sentencias switch para enviar el flujo de control a la rama correcta y durante el proceso de unificación en la programación lógica.

Puede haber múltiples definiciones válidas de igualdad, y cualquier lenguaje en particular puede adoptar una o más de ellas, dependiendo de varios aspectos de diseño. Un posible significado de igualdad es que "si a es igual a b , entonces a o b pueden usarse indistintamente en cualquier contexto sin notar ninguna diferencia". Pero esta afirmación no es necesariamente válida, en particular cuando se tiene en cuenta la mutabilidad junto con la igualdad de contenido.

Igualdad de ubicación vs. igualdad de contenido

A veces, especialmente en la programación orientada a objetos , la comparación plantea cuestiones de tipos de datos y herencia , igualdad e identidad . A menudo es necesario distinguir entre:

En muchos lenguajes de programación modernos, se accede a los objetos y las estructuras de datos a través de referencias . En dichos lenguajes, surge la necesidad de probar dos tipos diferentes de igualdad:

  • Igualdad estructural (es decir, sus contenidos son los mismos), que puede ser superficial (probar solo las subpartes inmediatas) o profunda (probar la igualdad de las subpartes de forma recursiva). Una forma sencilla de lograr esto es mediante la igualdad representacional: comprobar que los valores tienen la misma representación.
  • Otra igualdad hecha a medida, que preserva el comportamiento externo. Por ejemplo, 1/2 y 2/4 se consideran iguales cuando se los ve como un número racional. Un posible requisito sería que "A = B si y solo si todas las operaciones sobre los objetos A y B tendrán el mismo resultado", además de la reflexividad , la simetría y la transitividad .

El primer tipo de igualdad suele implicar el segundo (excepto en el caso de cosas como que no son números ( NaN ), que son desiguales entre sí), pero lo inverso no es necesariamente cierto. Por ejemplo, dos objetos de cadena pueden ser objetos distintos (desiguales en el primer sentido) pero contener la misma secuencia de caracteres (iguales en el segundo sentido). Consulte la sección sobre identidad para obtener más información sobre este tema.

Los números reales, incluidas muchas fracciones simples , no se pueden representar exactamente en aritmética de punto flotante , y puede ser necesario comprobar la igualdad dentro de una tolerancia dada. Sin embargo, dicha tolerancia puede romper fácilmente propiedades deseadas como la transitividad, mientras que la reflexividad también lo hace: el estándar IEEE de punto flotante requiere que se cumpla NaN ≠ NaN . Por el contrario, el estándar privado (2022) para aritmética posit (los defensores de posit pretenden reemplazar los flotantes IEEE) tiene un concepto similar, NaR (Not a Real), donde se cumple NaR = NaR . [1]

Otros elementos de programación, como las funciones computables, pueden no tener sentido de igualdad o tener un sentido de igualdad que no sea computable. Por estas razones, algunos lenguajes definen una noción explícita de "comparable", en forma de una clase base, una interfaz, un rasgo o un protocolo, que se utiliza explícitamente, mediante una declaración en el código fuente, o implícitamente, a través de la estructura del tipo involucrado.

Comparación de valores de diferentes tipos

En JavaScript , PHP , VBScript y algunos otros lenguajes de tipado dinámico , el operador de igualdad estándar sigue el llamado tipado flexible , es decir, se evalúa como verdadero incluso si dos valores no son iguales y son de tipos incompatibles, pero se puede obligar a que se vinculen entre sí mediante algún conjunto de reglas específicas del lenguaje, haciendo que el número 4 sea igual a la cadena de texto "4", por ejemplo. Aunque este comportamiento suele estar destinado a hacer que el lenguaje sea más sencillo, puede llevar a consecuencias sorprendentes y difíciles de predecir que muchos programadores desconocen. Por ejemplo, las reglas de igualdad flexibles de Javascript pueden hacer que la igualdad sea intransitiva (es decir, a == by b == c, pero a != c), o hacer que ciertos valores sean iguales a su propia negación. [2]

Un operador de igualdad estricta también suele estar disponible en esos lenguajes, que devuelve verdadero solo para valores con tipos idénticos o equivalentes (en PHP, 4 === "4"es falso aunque 4 == "4"es verdadero). [3] [4] Para los lenguajes donde el número 0 puede interpretarse como falso , este operador puede simplificar cosas como la verificación de cero (como x == 0sería verdadero para x siendo 0 o "0" usando el operador de igualdad independiente del tipo).

Realizar pedidos

La comparación de mayor que y menor que de datos no numéricos se realiza de acuerdo con una convención de clasificación (por ejemplo, para cadenas de texto, orden lexicográfico ) que puede estar incorporada en el lenguaje de programación y/o ser configurable por un programador.

Cuando se desea asociar un valor numérico con el resultado de una comparación entre dos elementos de datos, por ejemplo a y b , la convención habitual es asignar −1 si a < b, 0 si a = b y 1 si a > b. Por ejemplo, la función C strcmprealiza una comparación de tres vías y devuelve −1, 0 o 1 según esta convención, y qsort espera que la función de comparación devuelva valores según esta convención. En los algoritmos de ordenamiento , la eficiencia del código de comparación es fundamental, ya que es uno de los principales factores que contribuyen al rendimiento del ordenamiento.

La comparación de tipos de datos definidos por el programador (tipos de datos para los cuales el lenguaje de programación no tiene una comprensión incorporada) se puede realizar mediante funciones personalizadas o de biblioteca (como las strcmpmencionadas anteriormente) o, en algunos lenguajes, mediante la sobrecarga de un operador de comparación, es decir, asignando un significado definido por el programador que depende de los tipos de datos que se comparan. Otra alternativa es utilizar alguna convención, como la comparación miembro por miembro.

Equivalencia lógica

Aunque quizás no resulten obvios al principio, al igual que los operadores lógicos booleanos XOR, AND, OR y NOT, los operadores relacionales pueden diseñarse para que tengan equivalencia lógica , de modo que todos puedan definirse en términos de los demás. Las siguientes cuatro declaraciones condicionales tienen la misma equivalencia lógica E (todas verdaderas o todas falsas) para cualquier valor x e y dado:

Esto depende de que el dominio esté bien ordenado .

Operadores relacionales estándar

Los operadores relacionales numéricos más comunes utilizados en los lenguajes de programación se muestran a continuación. El SQL estándar utiliza los mismos operadores que BASIC, mientras que muchas bases de datos permiten !=además de <>los del estándar. SQL sigue el álgebra booleana estricta , es decir, no utiliza la evaluación de cortocircuito , que es común a la mayoría de los lenguajes que se indican a continuación. Por ejemplo, PHP lo tiene, pero por lo demás tiene estos mismos dos operadores definidos como alias, como muchas bases de datos SQL.

  1. ^ Incluye FORTRAN II, III, IV, 66 y 77.
  2. ^ ALGOL 68 : los regímenes de énfasis se utilizan en el código en plataformas con conjuntos de caracteres limitados ( por ejemplo , use >=o GEen lugar de ), plataformas sin bold énfasis (use 'ge') o plataformas con solo MAYÚSCULAS (use .GE o 'GE' ).
  3. ^ Incluyendo ALGOL , Simula , Modula-2 , Eiffel , SQL , fórmulas de hojas de cálculo y otros.
  4. ^ Modula-2 también reconoce#
  5. ^ Incluyendo C , C++ , C# , Go , Java , JavaScript , Perl ( solo comparación numérica), PHP , Python , Ruby y R.
  6. ^ Incluyendo Bourne Shell , Bash , KornShell y Windows PowerShell . Los símbolos <y >se utilizan normalmente en un shell para redirección , por lo que se deben utilizar otros símbolos. Sin el guion, se utiliza en Perl para la comparación de cadenas.
  7. ^ MATLAB, aunque en otros aspectos utiliza una sintaxis similar a la de C, no utiliza !=, ya que !en MATLAB envía el siguiente texto como línea de comando al sistema operativo . La primera forma también se utiliza en Smalltalk , con la excepción de la igualdad, que es =.
  8. ^ Incluyendo FORTRAN 95, 2003, 2008 y 2015.

Otras convenciones son menos comunes: Common Lisp y Macsyma / Maxima usan operadores similares a Basic para valores numéricos, excepto para la desigualdad, que está presente /=en Common Lisp y #en Macsyma/Maxima. Common Lisp tiene otros conjuntos de operadores de igualdad y relacionales que sirven para diferentes propósitos, incluyendo eq, eql, equal, equalp, y string=. [6] Los Lisp más antiguos usaban equal, greaterp, y lessp; y los negaban usando notpara los operadores restantes.

Sintaxis

Los operadores relacionales también se utilizan en la literatura técnica en lugar de palabras. Los operadores relacionales suelen escribirse en notación infija , si el lenguaje de programación lo admite, lo que significa que aparecen entre sus operandos (las dos expresiones están relacionadas). Por ejemplo, una expresión en Python imprimirá el mensaje si x es menor que y :

si  x  <  y :  print ( "x es menor que y en este ejemplo" )

Otros lenguajes de programación, como Lisp , utilizan la notación de prefijo , de la siguiente manera:

( >= X Y )  

Encadenamiento de operadores

En matemáticas, es una práctica común encadenar operadores relacionales, como en 3 < x < y < 20 (es decir, 3 < x y x < y e y < 20). La sintaxis es clara, ya que estos operadores relacionales en matemáticas son transitivos.

Sin embargo, muchos lenguajes de programación recientes considerarían una expresión como 3 < x < y como compuesta por dos operadores asociativos de izquierda (o derecha), interpretándola como algo así como (3 < x) < y. Si decimos que x=4, obtenemos (3 < 4) < y, y la evaluación dará true < ylo que generalmente no tiene sentido. Sin embargo, se compila en C/C++ y algunos otros lenguajes, lo que produce un resultado sorprendente (ya que true estaría representado por el número 1 aquí).

Es posible darle a la expresión x < y < zsu significado matemático habitual, y algunos lenguajes de programación como Python y Raku lo hacen. Otros, como C# y Java, no lo hacen, en parte porque diferiría de la forma en que la mayoría de los demás operadores infijos funcionan en lenguajes similares a C. El lenguaje de programación D no lo hace porque mantiene cierta compatibilidad con C, y "Permitir expresiones de C pero con semánticas sutilmente diferentes (aunque podría decirse que en la dirección correcta) agregaría más confusión que conveniencia". [7]

Algunos lenguajes, como Common Lisp , utilizan predicados de argumentos múltiples para esto. En Lisp (<= 1 x 10)es verdadero cuando x está entre 1 y 10.

Confusión con los operadores de asignación

El FORTRAN inicial (1956-57) estaba limitado por conjuntos de caracteres muy restringidos, donde =era el único operador relacional disponible. No existían <o >(y ciertamente no había o ). Esto obligó a los diseñadores a definir símbolos como .GT., .LT., .GE., .EQ.etc. y, posteriormente, hizo que fuera tentador usar el =carácter restante para copiar, a pesar de la incoherencia obvia con el uso matemático ( X=X+1debería ser imposible).

Lenguaje Algebraico Internacional (IAL, ALGOL 58 ) y ALGOL (1958 y 1960) se introdujeron así :=para la asignación, dejando el estándar =disponible para la igualdad, una convención seguida por CPL , ALGOL W , ALGOL 68 , Lenguaje Básico Combinado de Programación ( BCPL ), Simula , Lenguaje SET ( SETL ), Pascal , Smalltalk , Modula-2 , Ada , Estándar ML , OCaml , Eiffel , Object Pascal ( Delphi ), Oberon , Dylan , Lenguaje de Descripción de Hardware VHSIC ( VHDL ), y varios otros lenguajes.

B y C

Este estándar de facto uniforme entre la mayoría de los lenguajes de programación fue eventualmente cambiado, indirectamente, por un lenguaje compilado minimalista llamado B. Su única aplicación prevista era como vehículo para un primer puerto de Unix (en ese entonces muy primitivo) , pero también evolucionó hasta convertirse en el muy influyente lenguaje C.

B comenzó como una variante sintácticamente modificada del lenguaje de programación de sistemas BCPL , una versión simplificada (y sin tipos) de CPL . En lo que se ha descrito como un proceso de "desmantelamiento", los operadores andy de BCPL [8] fueron reemplazados por y (que luego se convertirían en y , respectivamente. [9] ). En el mismo proceso, el estilo ALGOL de BCPL fue reemplazado por en B. Se desconoce la razón de todo esto. [10] Como las actualizaciones de variables no tenían una sintaxis especial en B (como o similar) y se permitían en expresiones, este significado no estándar del signo igual significaba que la semántica tradicional del signo igual ahora tenía que asociarse con otro símbolo. Ken Thompson usó la combinación ad hoc para esto.or&|&&||:==let==

Cuando más tarde se introdujo un pequeño sistema de tipos, B se convirtió en C. La popularidad de este lenguaje, junto con su asociación con Unix, llevó a Java, C# y muchos otros lenguajes a seguir su ejemplo, sintácticamente, a pesar de este conflicto innecesario con el significado matemático del signo igual.

Idiomas

Las asignaciones en C tienen un valor y, dado que cualquier valor escalar distinto de cero se interpreta como verdadero en expresiones condicionales , [11] el código if (x = y)es legal, pero tiene un significado muy diferente de if (x == y). El primer fragmento de código significa "asignar y a x , y si el nuevo valor de x no es cero, ejecutar la siguiente instrucción". El último fragmento significa " si y solo si x es igual a y , ejecutar la siguiente instrucción". [12]

 int x = 1 ; int y = 2 ; if ( x = y ) { /* Este código siempre se ejecutará si y es cualquier cosa excepto 0*/ printf ( "x es %d e y es %d \n " , x , y ); }                 

Aunque Java y C# tienen los mismos operadores que C, este error suele provocar un error de compilación en estos lenguajes, porque la condición if debe ser del tipo boolean, y no hay una forma implícita de convertir otros tipos ( por ejemplo , números) a booleans. Por lo tanto, a menos que la variable a la que se asigna tenga el tipo boolean(o el tipo contenedor Boolean), habrá un error de compilación.

En lenguajes similares a ALGOL como Pascal, Delphi y Ada (en el sentido de que permiten definiciones de funciones anidadas ), y en Python y muchos lenguajes funcionales, entre otros, los operadores de asignación no pueden aparecer en una expresión (incluidas iflas cláusulas), lo que impide esta clase de error. Algunos compiladores, como GNU Compiler Collection (GCC), proporcionan una advertencia al compilar código que contiene un operador de asignación dentro de una declaración if, aunque existen algunos usos legítimos de una asignación dentro de una condición if. En tales casos, la asignación debe estar envuelta en un par de paréntesis adicionales de manera explícita, para evitar la advertencia.

De manera similar, algunos lenguajes, como BASIC, utilizan solo el =símbolo para asignación e igualdad, ya que están sintácticamente separados (como con Pascal, Ada, Python, etc., los operadores de asignación no pueden aparecer en expresiones).

Algunos programadores adquieren el hábito de escribir comparaciones contra una constante en el orden inverso al habitual:

 if ( 2 == a ) { /* El uso erróneo de = en lugar de == sería un error de tiempo de compilación */ }      

Si =se utiliza accidentalmente, el código resultante no es válido porque 2 no es una variable. El compilador generará un mensaje de error, en el que se puede sustituir el operador adecuado. Este estilo de codificación se denomina comparación por la izquierda o condiciones de Yoda .

Esta tabla enumera los diferentes mecanismos para probar estos dos tipos de igualdad en varios idiomas:

  1. ^ Solicitud de patente: El 14 de mayo de 2003, los empleados de Microsoft presentaron la solicitud estadounidense 20.040.230.959 "IS NOT OPERATOR" para el operador . Esta patente se concedió el 18 de noviembre de 2004. ISNOT

Ruby suele a === bsignificar "b es un miembro del conjunto a", aunque los detalles de lo que significa ser un miembro varían considerablemente dependiendo de los tipos de datos involucrados. ===se conoce aquí como el operador de "igualdad de caso" o "subsunción de caso".

Véase también

Notas y referencias

  1. ^ Norma para la aritmética de posiciones (2022)
  2. ^ Denys, Dovhan. "WTFJS". GitHub . Consultado el 25 de julio de 2024 .
  3. ^ Colaboradores. "Comparación de objetos". Manual de PHP . Grupo PHP . Consultado el 29 de junio de 2014 . {{cite web}}: |author=tiene nombre genérico ( ayuda ) ; Enlace externo en |author=( ayuda )
  4. ^ "PHP: Operadores de comparación - Manual" . Consultado el 31 de julio de 2008 .
  5. ^ Operadores relacionales y lógicos de Mathematica
  6. ^ "¿Por qué hay tantas formas de comparar para determinar la igualdad?". Stack Overflow . Consultado el 25 de julio de 2024 .
  7. ^ Alexandrescu, Andrei (2010). El lenguaje de programación D. Addison Wesley. pág. 58. ISBN 978-0-321-63536-5.
  8. ^ Se utiliza no sólo en lenguajes tipo ALGOL, sino también en FORTRAN y BASIC
  9. ^ Como algunos programadores estaban confundidos por los significados duales (operador bit a bit y conectivo lógico) de estos nuevos símbolos (según Dennis Ritchie ), solo se mantuvo el significado bit a bit de & y |.
  10. ^ Aunque Dennis Ritchie ha sugerido que esto puede tener que ver con la "economía de tipeo", ya que las actualizaciones de variables pueden ser más frecuentes que las comparaciones en ciertos tipos de programas.
  11. ^ Un valor escalar cero se interpreta como falso, mientras que cualquier valor escalar distinto de cero se interpreta como verdadero; esto se utiliza normalmente con tipos enteros, de forma similar a los modismos del lenguaje ensamblador .
  12. ^ Brian Kernighan y Dennis Ritchie (1988) [1978]. El lenguaje de programación C (segunda edición). Prentice Hall., 19