En informática , una comparación triple toma dos valores A y B pertenecientes a un tipo con un orden total y determina si A < B, A = B o A > B en una sola operación, de acuerdo con la ley matemática de la tricotomía .
Se puede implementar en términos de una función (como strcmpen C ), un método (como compareToen Java ) o un operador (como el operador de nave espacial<=> en Perl , PHP y C++ ).
Computación a nivel de máquina
La mayoría de los procesadores tienen conjuntos de instrucciones que admiten dicha operación en tipos primitivos. En algunas máquinas, las instrucciones de comparación establecen indicadores [ a ] que pueden ser probados por instrucciones de salto condicional subsiguientes. [ b ]
En algunas máquinas orientadas a palabras, las instrucciones de comparación son saltos , continuando en PC, PC+1 o PC+2 dependiendo del resultado de la comparación. [ c ] La mayoría de estas máquinas también tienen instrucciones de salto condicional.
Algunas máquinas utilizan enteros con signo basados en una representación de signo y magnitud o en complemento a uno (véase representaciones de números con signo ), las cuales permiten diferenciar entre cero positivo y negativo . Esto no infringe la tricotomía siempre que se adopte un orden total consistente: es válido que −0 = +0 o −0 < +0. Sin embargo, los tipos de punto flotante comunes presentan una excepción a la tricotomía: existe un valor especial "NaN" (que no es un número ) tal que x < NaN, x > NaN y x = NaN son falsos para todos los valores de punto flotante x (incluido el propio NaN).
Lenguajes de alto nivel
Talento
En C , las funciones strcmpy memcmprealizan una comparación triple entre cadenas y búferes de memoria, respectivamente. Devuelven un número negativo cuando el primer argumento es lexicográficamente menor que el segundo, cero cuando los argumentos son iguales y un número positivo en caso contrario. Esta convención de devolver el "signo de la diferencia" se extiende a funciones de comparación arbitrarias mediante la función de ordenación estándar qsort, que toma una función de comparación como argumento y requiere que se ajuste a ella.
En Perl (solo para comparaciones numéricas, el cmpoperador se usa para comparaciones léxicas de cadenas), PHP (desde la versión 7), Ruby y Apache Groovy , el "operador de nave espacial" <=>devuelve los valores −1, 0 o 1 dependiendo de si A < B, A = B o A > B, respectivamente. Las funciones de Python 2.x cmp(eliminadas en 3.x), OCamlcompare y KotlincompareTo calculan lo mismo. En la biblioteca estándar de Haskell , la función de comparación de tres vías está definida para todos los tipos en la clase ; devuelve el tipo , cuyos valores son (menor que), (igual a) y (mayor que): [ 3 ]compareOrdOrderingLTEQGT
Ordenación de datos = LT | EQ | GTMuchos lenguajes de programación orientados a objetos tienen una función de comparación triple , que realiza una comparación triple entre el objeto y otro objeto dado. Por ejemplo, en Java , cualquier clase que implemente la Comparableinterfaz tiene un compareTométodo que devuelve un entero negativo, cero o un entero positivo, o lanza una excepción NullPointerException(si uno o ambos objetos son null). De manera similar, en el marco .NET , cualquier clase que implemente la IComparableinterfaz tiene dicho CompareTométodo. En C++ , cualquier clase que pueda ser comparada triplemente puede ser un parámetro para instancias destd::compare_three_way , std::strong_order, std::weak_order, o std::partial_order.
Desde la versión 1.5 de Java, se puede calcular lo mismo utilizando el Math.signummétodo estático si se conoce la diferencia sin problemas computacionales como el desbordamiento aritmético mencionado más adelante. Muchos lenguajes de programación permiten la definición de funciones, por lo que se podría diseñar una función ` compare(A,B) ` adecuada, pero la cuestión es si su definición interna puede emplear algún tipo de sintaxis de tres vías o si, por el contrario, debe recurrir a pruebas repetidas.
Al implementar una comparación triple cuando no se dispone de un operador o método específico para dicha comparación, es común combinar dos comparaciones, como A = B y A < B, o A < B y A > B. En principio, un compilador podría deducir que estas dos expresiones podrían reemplazarse por una sola comparación seguida de múltiples pruebas del resultado, pero esta optimización no se menciona en los textos sobre el tema.
En algunos casos, la comparación triple se puede simular restando A y B y examinando el signo del resultado, aprovechando instrucciones especiales para analizar el signo de un número. Sin embargo, esto requiere que el tipo de A y B tenga una diferencia bien definida. Los enteros con signo de ancho fijo pueden desbordarse al restarlos, los números de coma flotante tienen el valor NaN con signo indefinido, y las cadenas de caracteres no tienen una función de diferencia que corresponda a su orden total. A nivel de máquina, el desbordamiento generalmente se controla y se puede usar para determinar el orden después de la resta, pero esta información generalmente no está disponible para los lenguajes de alto nivel.
En un caso de condicional de tres vías proporcionado por el lenguaje de programación, la instrucción IF aritmética de tres vías de Fortran , ahora obsoleta , considera el signo de una expresión aritmética y ofrece tres etiquetas a las que saltar según el signo del resultado:
SI ( expresión ) negativo , cero , positivoLa función de biblioteca común strcmp en C y lenguajes relacionados es una comparación lexicográfica de tres vías de cadenas; sin embargo, estos lenguajes carecen de una comparación general de tres vías de otros tipos de datos.
operador de naves espaciales
El operador de comparación de tres vías o "operador de nave espacial" para números se denota como <=>en Perl , Ruby , Apache Groovy , PHP , Eclipse Ceylon y C++ . [ 4 ]
En C++ , la revisión C++20 agrega el operador de nave espacial <=>, que devuelve un valor que codifica si los dos valores son iguales, menores, mayores o no ordenados y puede devolver diferentes tipos dependiendo de la rigurosidad de la comparación. [ 5 ]
El origen del nombre se debe a que le recordaba a Randal L. Schwartz la nave espacial de un juego de Star Trek en HP BASIC . [ 6 ] Otro programador ha sugerido que se le dio ese nombre porque se parecía al caza TIE de Darth Vader en la saga de Star Wars . [ 7 ]
Ejemplo en PHP:
eco 1 <=> 1 ; // 0 eco 1 <=> 2 ; // -1 eco 2 <=> 1 ; // 1Ejemplo en C++:
1 <=> 1 ; // se evalúa como std::strong_ordering::equal 1 <=> 2 ; // se evalúa como std::strong_ordering::less 2 <=> 1 ; // se evalúa como std::strong_ordering::greaterTipos de datos compuestos
Las comparaciones de tres vías tienen la ventaja de ser fáciles de componer y permiten construir comparaciones lexicográficas de tipos de datos no primitivos, a diferencia de las comparaciones de dos vías.
Aquí tenéis un ejemplo de composición en Perl.
sub compare ($$) { my ( $a , $b ) = @_ ; return $a -> { unit } cmp $b -> { unit } || $a -> { rank } <=> $b -> { rank } || $a -> { name } cmp $b -> { name }; }Nótese que cmp, en Perl, se usa para cadenas, mientras que <=>se usa para números. Los equivalentes bidireccionales tienden a ser menos compactos, pero no necesariamente menos legibles. Lo anterior aprovecha la evaluación de cortocircuito del ||operador y el hecho de que 0 se considera falso en Perl. Como resultado, si la primera comparación es igual (es decir, se evalúa como 0), pasará a la segunda comparación, y así sucesivamente, hasta que encuentre una que no sea cero, o hasta que llegue al final.
En algunos lenguajes, como Python , Ruby , Haskell , etc., la comparación de listas se realiza lexicográficamente, lo que significa que es posible construir una cadena de comparaciones como el ejemplo anterior colocando los valores en listas en el orden deseado; por ejemplo, en Ruby:
[ a . unidad , a . rango , a . nombre ] <=> [ b . unidad , b . rango , b . nombre ]En C++:
std :: tie ( a.unit , a.rank , a.name ) <=> std :: tie ( b.unit , b.rank , b.name )Operador de unión SQL
En algunos dialectos SQL , <=>se utiliza como un operador de unión seguro contra valores nulos que hará coincidir los operandos si ambos son nulos. [ 8 ]
Véase también
Notas
- ↑ Las distintas máquinas tienen una nomenclatura diferente; algunos términos comunes son código de condición , bandera , indicador y estado .
- ↑ Por ejemplo, comparar con A (CMPA), comparar con Q (CMPQ), comparar con AQ (CMPAQ), comparar con X n (CMPXn), comparar con límites (CWL), comparar magnitud (CMG), en el GE 635 [ 1 ]
- ↑ Por ejemplo, compare el acumulador con el almacenamiento (CAS) y compare el acumulador lógico con el almacenamiento (LAS) en el IBM 7094. [ 2 ]
Referencias
- ↑ "Comparación--Comparar" (PDF) . Manual de referencia de programación GE-635 (PDF) . LOS COMPATIBLES/600. GE . Julio de 1964. págs. II-83 – II-88 . CPB-1004 . Consultado el 6 de abril de 2025 .
- ↑ "Instrucciones de control" (PDF) . Principios de funcionamiento del IBM 7094 (PDF) . Biblioteca de referencia de sistemas. pág. 53. A22-6703-4 . Consultado el 22 de septiembre de 2025 .
- ↑ Data.Ord
- ↑ "Math::Complex" . Documentación de programación en Perl . Consultado el 26 de septiembre de 2014 .
- ↑ Herb Sutter propuso añadir un operador de comparación de tres vías al estándar C++ con lasintaxis, en un documento titulado "Consistent Comparison". Véase "Consistent Comparison" . Se integró con éxito en el borrador de C++20 en noviembre de 2017.
<=> - ↑ "Historia de la nave espacial (era Re: [ dart-misc ] notas de la reunión del DEP)" .
- ↑ "Operador de supernave espacial" . 8 de diciembre de 2000. Consultado el 6 de agosto de 2014 .
- ↑ https://dev.mysql.com/doc/refman/8.4/en/comparison-operators.html#operator_equal-to
- Construcciones condicionales
- Operadores (programación)