Comparação trilateral

Na informática , uma comparação trilateral toma dois valores A e B pertencentes a um tipo com relação de ordem total e determina se A <B, A = B ou A> B em uma única operação, de acordo com a matemática da lei de tricotomia .

Cálculo de nível de máquina

Muitos processadores têm conjuntos de instruções que suportam essa operação em tipos primitivos. Algumas máquinas têm números inteiros com sinal baseados no complemento de um (ver representação de números inteiros negativos ), o que permite diferenciar entre um zero positivo e um zero negativo. Isso não viola a tricotomia, desde que uma ordem total consistente seja adotada: as opções -0 = +0 e -0 <+0 são ambas válidas. Os tipos de ponto flutuante , no entanto, têm uma exceção à tricotomia: há um valor especial "NaN" ( não é um número ) tal que x <NaN, x > NaN e x = NaN são todos falsos para todos os valores. Ponto flutuante x ( incluindo o próprio NaN).

Linguagens de alto nível

Em C , funciona strcmpe memcmprealiza uma comparação trilateral entre strings e buffers de memória, respectivamente. Eles retornam um número negativo quando o primeiro argumento é menor que o segundo (do ponto de vista lexicográfico ), zero quando os argumentos são iguais e um número positivo caso contrário. Essa convenção de retornar o "sinal da diferença" é arbitrariamente estendida para funções de comparação pela função de classificação padrão qsort, que recebe uma função de comparação como um argumento e a usa para classificar itens. C ++ 20 adiciona o "operador de nave espacial" <=>, que retorna o sinal da diferença e também pode retornar diferentes tipos (conversíveis em inteiros com sinal) dependendo se a comparação é estrita ou não.

Em Perl (apenas para comparações numéricas, cmp é usado para comparações lexicais de strings), PHP (desde a versão 7), Ruby e Apache Groovy , o "operador de nave espacial" <=>retorna os valores -1, 0 ou 1 dependendo se A <B, A = B ou A> B, respectivamente. Em Python 2.x (removido em 3.x), OCaml e Kotlin , funções cmp, comparee compareTocalcular a mesma, respectivamente. Na biblioteca padrão Haskell , a função de comparação trilateral compareé definida para todos os tipos da classe Ord; ele retorna o tipo Ordering, cujos valores são LT(menor que, para menor que ), EQ(igual, para EQual ) e GT(mais que, para maior que ). Muitas linguagens orientadas a objetos têm um método de comparação trilateral, que realiza uma comparação trilateral entre o objeto e outro determinado objeto. Por exemplo, em Java , qualquer classe que implementa a interface Comparabletem um método compareToque retorna um inteiro negativo, zero ou um inteiro positivo, ou lança um NullPointerException(se um ou ambos os objetos forem null). Da mesma forma, no .NET Framework , qualquer classe que implemente a interface IComparablepossui um método CompareToequivalente.

A partir do Java versão 1.5, o mesmo pode ser calculado usando o método estático Math.signumse a diferença puder ser conhecida sem problemas de cálculo, como estouro de inteiro mencionado abaixo. Muitas linguagens de computador permitem a definição de funções para que uma comparação (A, B) possa ser projetada apropriadamente, mas a questão é se sua definição interna será baseada em sintaxe trilateral ou em testes repetidos.

Ao implementar uma comparação trilateral quando um operador ou um método de comparação trilateral ainda não está disponível, é comum combinar duas comparações, como A = B e A <B ou A <B e A> B. Em princípio, um compilador pode deduzir que essas duas expressões poderiam ser substituídas por uma única comparação seguida de vários testes sobre o resultado, mas a menção a essa otimização parece não existir nos diversos textos sobre o assunto.

Em alguns casos, a comparação trilateral pode ser simulada subtraindo A e B e examinando o sinal do resultado, usando instruções especiais para estudar o sinal de um número. No entanto, isso requer que o tipo de A e B tenham uma diferença bem definida. Inteiros com sinal de largura fixa podem estourar, números de ponto flutuante podem ser NaN com um sinal indefinido e as strings não têm função de diferença correspondente à sua ordem total. No nível da máquina, um estouro será rastreado e pode ser usado para determinar a ordem após uma subtração, mas essas informações geralmente não estão disponíveis em linguagens de nível superior.

Mesmo que seja obsoleta hoje, a declaração aritmética IF do Fortran forneceu uma instrução condicional trilateral que permitia pular para 3 rótulos de acordo com o sinal do resultado: A função strcmp em C (e linguagens relacionadas) é uma comparação lexicográfica trilateral de strings de personagens. No entanto, essas linguagens carecem de um operador de comparação trilateral genérico.

Tipos de dados compostos

As comparações trilaterais têm a particularidade de serem fáceis de compor e de construir comparações lexicográficas de tipos não primitivos, ao contrário das comparações bilaterais.

Aqui está um exemplo de composição em Perl. Observe que cmp, em Perl, é para strings, enquanto =>é para números. Equivalentes bilaterais tendem a ser menos compactos, mas não necessariamente menos legíveis. O exemplo acima tira vantagem da avaliação "Shorted" do operador ||e do fato de 0 ser considerado falso em Perl. Conseqüentemente, se a primeira comparação der "igual" (portanto avaliado em 0), ela "cruzará" a segunda comparação, e assim por diante, até encontrar uma que seja diferente de zero, ou até 'até chegar ao fim.

Em algumas linguagens, incluindo Python , Ruby , Haskell , etc., a comparação de listas é feita lexicograficamente, o que significa que é possível construir uma cadeia de comparações, como no exemplo acima, colocando os valores em listas em a ordem desejada; por exemplo, em Ruby:

Proposta para C ++

Em 5 de fevereiro de 2017, Herb Sutter propôs adicionar um terceiro operador de comparação, denominado "operador de nave espacial", ao padrão C ++ com sintaxe <=>, em um artigo intitulado "Comparação consistente".

Ele foi incorporado ao projeto C ++ 20 em novembro de 2017.

Curiosidades

O operador de comparação para números é escrito <=>em Perl , Ruby , Apache Groovy , PHP e Eclipse Ceylon , e é chamado de operador de nave espacial porque lembrou Randal L. Schwartz de uma nave espacial em um jogo HP BASIC Star . outro programador sugeriu que ele foi nomeado assim porque ele se parecia com o lutador TIE de Darth Vader na saga Star Wars .

Veja também

Referências

  1. Data.Ord
  2. Comparação consistente
  3. "  Math :: Complex  " , da documentação de programação Perl (acessado em 26 de setembro de 2014 )
  4. "  História da espaçonave (foi Re: [dardo-misc] notas da reunião DEP)  "
  5. "  Super Spaceship Operator  " ,8 de dezembro de 2000(acessado em 6 de agosto de 2014 )