Articulo de referencia

Operador relacional

En informática , un operador relacional es una construcción u operador de un lenguaje de programación que define sintácticamente una relación entre dos entidades. Esto incluye l...

En informática , un operador relacional es una construcción u operador de un lenguaje de programación que define sintácticamente una relación entre dos entidades. Esto incluye la igualdad numérica (por ejemplo, 5 = 5 ) y las desigualdades (por ejemplo, 4 ≥ 3 ).

En los lenguajes de programación que incluyen un tipo de dato booleano distinto en su sistema de tipos , como Pascal , Ada , Python o Java , estos operadores suelen evaluarse como verdaderos o falsos, dependiendo de si se cumple o no la relación condicional entre los dos operandos .

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 numerosas construcciones de lenguajes de programación y tipos de datos. Se emplea para comprobar si un elemento ya existe en un conjunto o para acceder a un valor mediante una clave. También se utiliza en las sentencias switch para dirigir el flujo de control a la rama correcta y durante el proceso de unificación en la programación lógica.

Existen múltiples definiciones válidas de igualdad, y cualquier idioma puede adoptar una o más de ellas, según diversos aspectos de su 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 que se note ninguna diferencia». Sin embargo, esta afirmación no siempre se cumple, sobre todo si se tiene en cuenta la mutabilidad junto con la igualdad de contenido.

Igualdad de ubicación frente a igualdad de contenido

En ocasiones, sobre todo 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:

  • dos objetos diferentes del mismo tipo, por ejemplo, dos manos
  • dos objetos iguales pero distintos, por ejemplo, dos billetes de 10 dólares.
  • Dos objetos iguales pero con diferente representación, por ejemplo, un billete de $1 y una moneda de $1.
  • dos referencias diferentes al mismo objeto, por ejemplo, dos apodos para la misma persona.

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

  • Igualdad de ubicación (identidad): si dos referencias (A y B) hacen referencia al mismo objeto, las interacciones con el objeto a través de A son indistinguibles de las mismas interacciones a través de B, y en particular, los cambios realizados en el objeto a través de A se reflejan a través de B.
  • Igualdad de contenido: si los objetos referenciados por dos referencias (A y B) son equivalentes en algún sentido:
  • Igualdad estructural (es decir, que su contenido sea el mismo). Esta igualdad puede ser superficial (comprobando solo las subpartes inmediatas) o profunda (comprobando la igualdad de las subpartes de forma recursiva). Una forma sencilla de lograrlo es mediante la igualdad representacional: comprobar que los valores tengan la misma representación.
  • Alguna otra igualdad hecha a medida, que preserve el comportamiento externo. Por ejemplo, 1/2 y 2/4 se consideran iguales cuando se ven como números racionales. 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 reflexividad , simetría y transitividad .

La primera igualdad suele implicar la segunda (excepto en el caso de valores como NaN , que son distintos entre sí), pero lo contrario no es necesariamente cierto. Por ejemplo, dos cadenas de caracteres pueden ser distintas (distintas en el primer sentido) pero contener la misma secuencia de caracteres (iguales en el segundo). Consulte la sección sobre identidad para obtener más información al respecto.

Los números reales, incluidas muchas fracciones simples , no pueden representarse con exactitud en aritmética de punto flotante , y puede ser necesario comprobar la igualdad dentro de una tolerancia determinada. Sin embargo, dicha tolerancia puede romper fácilmente propiedades deseadas como la transitividad, mientras que la reflexividad también se rompe: el estándar de punto flotante IEEE exige que se cumpla NaN ≠ NaN . En contraste, el estándar privado (2022) para aritmética posit (los defensores de posit pretenden reemplazar los números de punto flotante 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 carecer de igualdad o tener una igualdad que no sea computable. Por estas razones, algunos lenguajes definen una noción explícita de "comparable" en forma de clase base, interfaz, rasgo o protocolo, que se utiliza explícitamente, mediante su 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 pueden convertir entre sí mediante un conjunto de reglas específicas del lenguaje, haciendo que el número 4 se compare como igual a la cadena de texto "4", por ejemplo. Aunque este comportamiento generalmente está pensado para simplificar el lenguaje, puede tener 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 ), o hacer que ciertos valores sean iguales a su propia negación. [ 2 ]a != c

También suele estar disponible un operador de igualdad estricta 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 lenguajes donde el número 0 puede interpretarse como falso , este operador puede simplificar cosas como comprobar si es cero (como x == 0sería verdadero para x siendo 0 o "0" usando el operador de igualdad independiente del tipo).

Pedidos

La comparación de valores mayores y menores que en datos no numéricos se realiza según una convención de ordenación (como, en el caso de cadenas de texto, el orden lexicográfico ), que puede estar integrada en el lenguaje de programación o ser configurable por el programador.

Cuando se desea asociar un valor numérico al 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 de C strcmprealiza una comparación triple 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 ordenación , la eficiencia del código de comparación es fundamental, ya que es uno de los principales factores que contribuyen al rendimiento de la ordenación.

La comparación de tipos de datos definidos por el programador (tipos de datos para los que el lenguaje de programación no tiene una comprensión integrada) puede realizarse mediante funciones personalizadas o de biblioteca (como las strcmpmencionadas anteriormente) o, en algunos lenguajes, sobrecargando un operador de comparación; es decir, asignándole 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 a miembro.

Equivalencia lógica

Aunque al principio pueda parecer poco obvio, al igual que los operadores lógicos booleanos XOR, AND, OR y NOT, los operadores relacionales pueden diseñarse para tener equivalencia lógica , de modo que todos puedan definirse en términos unos de otros. Las siguientes cuatro proposiciones condicionales tienen la misma equivalencia lógica E (todas verdaderas o todas falsas) para cualquier par de valores x e y dados :

mi={incógnita<yy>incógnitaincógnitayyincógnita{\displaystyle E={\begin{casos}x<y\\y>x\\x\ngeq y\\y\nleq x\end{casos}}}

Esto depende de que el dominio esté bien ordenado .

Operadores relacionales estándar

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

  1. Incluyendo FORTRAN II, III, IV, 66 y 77.
  2. ALGOL 68 : los regímenes de stropping se utilizan en el código en plataformas con conjuntos de caracteres limitados ( por ejemplo , use>=oGEen lugar de), plataformas sinbold énfasis (use'ge'), o plataformas con solo MAYÚSCULAS (use.GE o'GE' ).
  3. Incluye ALGOL , Simula , Modula-2 , Eiffel , SQL , fórmulas de hojas de cálculo y otros.
  4. Modula-2 también reconoce#
  5. Incluye C ,C ++ , C# , Go , Java , JavaScript , Perl (solo comparación numérica), PHP , Python , Ruby y R.
  6. Incluye Bourne shell , Bash , KornShell y Windows PowerShell . Los símbolos<y>se utilizan normalmente en un shell para la redirección , por lo que deben utilizarse 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!MATLAB envía el siguiente texto como una línea de comandos al sistema operativo . La primera forma también se utiliza en Smalltalk , con la excepción de la igualdad, que es=.
  8. Incluye 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á /=en Common Lisp y #en Macsyma/Maxima. Common Lisp tiene varios 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 : imprimir ( "x es menor que y en este ejemplo" )

Otros lenguajes de programación, como Lisp , utilizan la notación prefija , como se muestra a continuación:

( >= X Y )

encadenamiento de operadores

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

Sin embargo, muchos lenguajes de programación recientes verían una expresión como 3 < x < y como compuesta por dos operadores asociativos izquierdos (o derechos), interpretándola como algo como (3 < x) < y. Si decimos que x=4, entonces obtenemos (3 < 4) < y, y la evaluación dará true < ylo cual generalmente no tiene sentido. Sin embargo, compila en C/C++ y algunos otros lenguajes, produciendo un resultado sorprendente (ya que verdadero 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, en parte porque diferiría del funcionamiento de la mayoría de los demás operadores infijos en lenguajes similares a C. El lenguaje de programación D no lo hace, ya que mantiene cierta compatibilidad con C, y «Permitir expresiones de C, pero con una semántica sutilmente diferente (aunque posiblemente en la dirección correcta), generaría más confusión que conveniencia». [ 7 ]

Algunos lenguajes, como Common Lisp , utilizan predicados con múltiples argumentos 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 había ni <o >(y ciertamente no ni o ). Esto obligó a los diseñadores a definir símbolos como .GT., .LT., .GE., .EQ.etc., y posteriormente hizo tentador usar el =carácter restante para copiar, a pesar de la obvia incoherencia con el uso matemático ( X=X+1debería ser imposible).

El lenguaje algebraico internacional (IAL, ALGOL 58 ) y ALGOL (1958 y 1960) se introdujeron :=para la asignación, dejando el estándar =disponible para la igualdad, una convención seguida por 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 ) y varios otros lenguajes.

B y C

Este estándar uniforme de facto entre la mayoría de los lenguajes de programación fue modificado, indirectamente, por un lenguaje compilado minimalista llamado B. Su única aplicación prevista era servir como vehículo para una primera adaptación de (un entonces muy primitivo) Unix , pero también evolucionó hasta convertirse en el 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 "despojamiento", los operadores andy de BCPL [ 8 ] fueron reemplazados por y (que más tarde 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 estaban permitidas 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 posteriormente se introdujo un sistema de tipos reducido, B pasó a llamarse C. La popularidad de este lenguaje, junto con su asociación con Unix, llevó a que Java, C# y muchos otros lenguajes siguieran su ejemplo, sintácticamente, a pesar de este conflicto innecesario con el significado matemático del signo de igualdad.

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 válido, 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 segundo 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 distinto de 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 de tipo boolean, y no hay una forma implícita de convertir de otros tipos ( por ejemplo , números) a boolean. Así que, a menos que la variable que se asigna a tenga tipo boolean(o tipo contenedor Boolean), habrá un error de compilación.

En lenguajes tipo 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 excluye este tipo de error. Algunos compiladores, como GNU Compiler Collection (GCC), emiten una advertencia al compilar código que contiene un operador de asignación dentro de una sentencia if, aunque existen algunos usos legítimos de una asignación dentro de una condición if. En tales casos, la asignación debe ir explícitamente entre paréntesis adicionales para evitar la advertencia.

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

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

// El uso erróneo de = frente a == sería un error de compilación si ( 2 == a ) { // ... }

Si =se usa 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 correcto. Este estilo de codificación se denomina comparación por la izquierda o condiciones de Yoda .

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

  1. Solicitud de patente: El 14 de mayo de 2003,empleados de Microsoft presentaron la solicitud estadounidense n.º 20,040,230,959 «IS NOT OPERATOR» para el operador . Esta patente fue concedida el 18 de noviembre de 2004. ISNOT

Ruby usa a === bpara significar "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. ===Aquí se conoce como el operador de "igualdad de casos" o "subsunción de casos".

Véase también

Notas y referencias

  1. Estándar para la aritmética positiva (2022)
  2. ^ Denys, Dovhan. "WTFJS" . GitHub . Consultado el 25 de julio de 2024 .
  3. "Comparación de objetos" . Manual de PHP . Grupo PHP . Consultado el 29 de junio de 2014 .
  4. "PHP: Comparación de operadores - Manual" . Consultado el 31 de julio de 2008 .
  5. Operadores relacionales y lógicos de Mathematica
  6. "¿Por qué hay tantas maneras 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 solo en lenguajes tipo ALGOL, sino también en FORTRAN y BASIC.
  9. Algunos programadores se confundieron con los significados duales (operador bit a bit y conector lógico) de estos nuevos símbolos (según Dennis Ritchie ). Solo se conservó el significado bit a bit de & y |.
  10. Aunque Dennis Ritchie ha sugerido que esto puede tener que ver con la "economía de escritura", 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 usa normalmente con tipos enteros, de forma similar a las convenciones del lenguaje ensamblador .
  12. Brian Kernighan y Dennis Ritchie (1988) [1978]. El lenguaje de programación C (Segunda edición). Prentice Hall. , 19