stringtranslate.com

Comparación de tres vías

En informática , una comparación de tres vías 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 tricotomía .

Puede implementarse en términos de una función (como strcmpen C ), un método (como compareToen Java ) o un operador (como el operador de la nave espacial <=> en Perl ).

Computación a nivel de máquina

Muchos procesadores tienen conjuntos de instrucciones que admiten dicha operación en tipos primitivos. Algunas máquinas tienen enteros con signo basados ​​en una representación de signo y magnitud o en complemento de uno (ver representaciones de números con signo ), las cuales permiten un cero positivo y negativo diferenciados . Esto no viola la tricotomía siempre que se adopte un orden total consistente: −0 = +0 o −0 < +0 es válido. Los tipos de punto flotante comunes , sin embargo, tienen una excepción a la tricotomía: hay un valor especial "NaN" ( No es un número ) tal que x < NaN, x > NaN y x = NaN son todos falsos para todos los valores de punto flotante x (incluido el propio NaN).

Idiomas de alto nivel

Habilidades

En C , las funciones strcmpy memcmprealizan una comparación de tres vías 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 clasificación estándar qsort, que toma una función de comparación como argumento y le exige que la cumpla.

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 Python 2.x cmp(eliminadas en 3.x), OCaml compare y Kotlin compareTo 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 de la clase ; devuelve tipo , cuyos valores son (menor que), (igual) y (mayor que): [1]compareOrd OrderingLTEQGT

datos Pedido = LT | Ecualizador | GT       

Muchos lenguajes de programación orientados a objetos tienen un método de comparación de tres vías , que realiza una comparación de tres vías entre el objeto y otro objeto determinado. Por ejemplo, en Java , cualquier clase que implemente la Comparableinterfaz tiene un método compareTo que devuelve un entero negativo, cero o un entero positivo, o arroja un NullPointerException(si uno o ambos objetos son null). De manera similar, en el marco .NET , cualquier clase que implemente la IComparableinterfaz tiene dicho método CompareTo.

Desde la versión 1.5 de Java, lo mismo se puede calcular utilizando el Math.signummétodo estático si la diferencia se puede conocer sin problemas computacionales como el desbordamiento aritmético que se menciona a continuación. Muchos lenguajes informáticos permiten la definición de funciones, por lo que una comparación (A, B) podría diseñarse apropiadamente, pero la pregunta es si su definición interna puede emplear algún tipo de sintaxis de tres vías o si debe recurrir a pruebas repetidas.

Al implementar una comparación de tres vías donde aún no está disponible un operador o método de comparación de tres vías, 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 sustituirse por una sola comparación seguida de múltiples pruebas del resultado, pero no se menciona esta optimización en los textos sobre el tema.

En algunos casos, se puede simular una comparación triple restando A y B y examinando el signo del resultado, aprovechando instrucciones especiales para examinar 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 cuando se restan, los números de punto flotante tienen el valor NaN con signo indefinido y las cadenas de caracteres no tienen ninguna función de diferencia correspondiente a su orden total. A nivel de máquina, generalmente se rastrea el desbordamiento y se puede usar para determinar el orden después de la resta, pero esta información generalmente no está disponible para lenguajes de nivel superior.

En un caso de un condicional de tres vías proporcionado por el lenguaje de programación, la ahora obsoleta declaración IF aritmética de tres vías de Fortran considera el signo de una expresión aritmética y ofrece tres etiquetas para saltar de acuerdo con el signo del resultado:

 SI ( expresión ) negativo , cero , positivo  

La 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 nave espacial

El operador de comparación de tres vías u "operador de nave espacial" para números se denomina como <=>en Perl , Ruby , Apache Groovy , PHP , Eclipse Ceilán y C++ , y se denomina operador de nave espacial . [2]

En C++ , la revisión de C++ 20 agrega el operador de nave espacial <=>, que de manera similar devuelve el signo de la diferencia y también puede devolver diferentes tipos (convertibles a enteros con signo) dependiendo del rigor de la comparación. [3]

El origen del nombre se debe a que a Randal L. Schwartz le recuerda a la nave espacial de un juego HP BASIC Star Trek . [4] Otro programador ha sugerido que se llamó así porque se parecía al caza TIE de Darth Vader en la saga Star Wars . [5]

Ejemplo en PHP:

eco  1  <=>  1 ;  // 0 eco  1  <=>  2 ;  // -1 eco  2  <=>  1 ;  // 1

Tipos de datos compuestos

Las comparaciones tripartitas tienen la propiedad de ser fáciles de componer y construir comparaciones lexicográficas de tipos de datos no primitivos, a diferencia de las comparaciones bidireccionales.

A continuación se muestra un ejemplo de composición en Perl.

sub comparar ($$) { mi ( $a , $b ) = @_ ; return $a -> { unidad } cmp $b -> { unidad } || $a -> { rango } <=> $b -> { rango } || $a -> { nombre } cmp $b -> { nombre }; }                   

Tenga en cuenta que cmp, en Perl, es para cadenas, ya que <=>es 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 (por lo tanto, se evalúa como 0), "caerá" en la segunda comparación, y así sucesivamente, hasta que encuentre una que sea distinta de cero, o hasta que llegue al final.

En algunos lenguajes, incluidos 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 Rubí:

[ a . unidad , un . rango , un . nombre ] <=> [ b . unidad , b . rango , b . nombre ]      

Ver también

Referencias

  1. ^ Datos.Ord
  2. ^ "Matemáticas :: Complejo". Documentación de programación en Perl . Consultado el 26 de septiembre de 2014 .
  3. ^ Herb Sutter propuso agregar un operador de comparación de tres vías al estándar C++ con la <=>sintaxis, en un artículo titulado "Comparación consistente". Consulte "Comparación coherente". Se fusionó con éxito en el borrador de C++ 20 en noviembre de 2017.
  4. ^ "Historia de la nave espacial (era Re: [dart-misc] notas de la reunión del DEP)".
  5. ^ "Operador de súper nave espacial". 2000-12-08 . Consultado el 6 de agosto de 2014 .