PHP é famoso por seu malabarismo de tipos. Devo admitir que isso me intriga, e estou tendo dificuldade em descobrir coisas lógicas / fundamentais básicas em comparações.
Por exemplo: se $a > $b
é verdadeiro e $b > $c
verdadeiro, isso significa que sempre$a > $c
é verdadeiro também?
Seguindo a lógica básica, eu diria que sim, mas estou tão perplexo que realmente não confio no PHP nisso. Talvez alguém possa dar um exemplo em que este não seja o caso?
Além disso, estou me perguntando com os operadores estrito menor que e estrito maior que (já que seu significado é descrito como estritamente que eu só conhecia no passado a partir das comparações de igualdade) se faz alguma diferença se os operandos esquerdo e direito são trocados com valores estritamente desiguais:
# Precondition:
if ($a === $b) {
throw new Exception(
'Both are strictly equal - can not compare strictly for greater or smaller'
);
}
($a > $b) !== ($b > $a)
Para a maioria das combinações de comparação de tipo, esses operadores de comparação maiores / menores não são documentados, portanto, a leitura do manual não foi realmente útil neste caso.
fonte
($a > $b) !== ($b < $a)
?Respostas:
Os operadores de comparação do PHP se desviam das definições científicas do computador de várias maneiras:
Para constituir uma relação de equivalência
==
deve ser reflexiva, simétrica e transitiva:O
==
operador do PHP não é reflexivo , ou$a == $a
seja, nem sempre é verdadeiro:Nota: O fato de que qualquer comparação envolvendo
NAN
semprefalse
não é específico do PHP. É exigido pelo padrão IEEE 754 para aritmética de ponto flutuante ( mais informações ).Do PHP
==
operador é simétrica , ou seja,$a == $b
e$b == $a
são sempre os mesmos.Do PHP
==
operador é não transitiva , ou seja, a partir$a == $b
e$b == $c
se não se segue$a == $c
:Para constituir uma ordem parcial
<=
/>=
tem que ser reflexiva, anti-simétrica e transitiva:O
<=
operador do PHP não é reflexivo , ou$a <= $a
seja, nem sempre é verdadeiro (exemplo mesmo que para==
).O
<=
operador do PHP não é anti-simétrico , ou seja, de$a <= $b
e$b <= $a
não segue$a == $b
:O
<=
operador do PHP não é transitivo , ou seja, de$a <= $b
e$b <= $c
não segue$a <= $c
(Exemplo igual a==
).Extra: o
<=
operador do PHP não é total , ou seja, ambos$a <= $b
e$b <= $a
pode ser falso:A fim de constituir uma ordem parcial estrita,
<
/>
deve ser irreflexiva, assimétrica e transitiva:O
<
operador do PHP é irreflexivo , ou$a < $a
seja, nunca é verdadeiro. Observe que isso é verdade apenas a partir do PHP 5.4 . AnteriormenteINF < INF
avaliado paratrue
.O
<
operador do PHP não é assimétrico , ou seja, de$a < $b
não segue!($b < $a)
(Exemplo igual para<=
não ser anti-simétrico).O
<
operador do PHP não é transitivo , ou seja, de$a < $b
e$b < $c
não segue$a < $c
:Extra: o
<
operador do PHP não é tricotômico , ou seja, todo$a < $b
,$b < $a
e$a == $b
pode ser falso (exemplo mesmo de<=
não ser total).Extra: o
<
operador do PHP pode ser circular , ou seja, é possível que$a < $b
,$b < $c
e$c < $a
:Nota: O exemplo acima lança um aviso "Objeto da classe stdClass não pôde ser convertido em duplo".
Você pode encontrar alguns gráficos legais para os operadores de comparação do PHP em PHP Sadness 52 - Operadores de comparação .
Como uma última nota, eu quero salientar que existem duas igualdades que o PHP faz garantia (ao contrário de muito tudo muito mais). Esses dois sempre são válidos, simplesmente porque o compilador reduz um ao outro:
fonte
($a > $b) and ($b > $c)
com$a > $c
mesmo que a documentação diz que aqueles<
/>
operadores dizem que são rigorosa ?$a == $b
é o mesmo que(type) $a === (type) $b
. Um exemplo simples disso é aquele"15" == "0xf"
, mas(int) "15" !== (int) "0xf"
. E as regras de comparação e cast em PHP são totalmente malucas ^^(int)"0xf"
avalia como inteiro0
, então é claro0 !== 15
. A comparação neste exemplo se comporta exatamente como esperado. É o elenco que está confuso aqui. Admito que(INF < INF) === true
foi um problema genuíno de comparação, mas foi um caso especial e foi resolvido como você apontou. Ótima resposta .. +1Não há operadores de comparação estritamente idênticos (
>==
ou<==
) no PHP (pelo PHP 5.6.14 pelo menos) , mas existem algumas maneiras de impor uma verificação de tipo estrita antes de marcar Maior / Menor:if (gettype($a) === gettype($b))
if ((string)$a === (string)$b)
if (($a . '') === ($b . ''))
Observe que:
INF
eNAN
são do tipofloat
sobieee754e
é sempre do tipofloat
, e nuncainteger
mesmo se o número for pequenoPHP_INT_MAX
são convertidos automaticamente parafloat
INF
valorNULL
0
são convertidos de octal para decimal (por convenção)0
em tiras de um inteiro à esquerda0
Lista de algumas comparações exóticas:
Igual, mas não idêntico:
Menor e maior ao mesmo tempo?
Igual E idêntico:
Menor ou Maior:
$a > $b > $c
Enigma quando:$a
não é maior que$c
.Comparação de strings divertida: 'Rainha'
>
'Rei'>
'Valete'>
'Ás'Verifique também as tabelas de comparação de tipos de PHP que abrangem pares:
isset()
eis_null()
if()
eempty()
==
vs.===
Verifique as diferenças entre as versões do PHP ao vivo em. http://3v4l.org/MAfDu .
fonte
if ( (string)$a===(string)$b )
mas não é exatamente o mesmo queif ( (string)$a==(string)$b )
?(string)1==(string)'01'
->bool(true)
e para type-juggle(1 . '')=='01'
->bool(true)
não exatamente o mesmo que===
quando você receberiabool(false)
em ambas as contasINFINITY is equal to INFINITY which is mathematically incorrect!
é uma declaração decididamente discutível. Observe também queNaN
é por convenção não maior, menor ou igual a qualquer coisa em qualquer linguagem de programação que eu conheça.Após sua correção da segunda parte de sua pergunta, deixo a resposta dessa parte para os demais. Eu só quero dar a resposta mais surpreendente para a primeira parte de sua pergunta, ou seja, se há um exemplo de operadores
<
e>
sendo intransitivos. Aqui está.Estes são todos
true
:Se
<
fosse transitivo ($a < $b
∧$b < $c
⇒$a < $c
), a última linha seriamas o PHP tenta ser gentil (?!) e interpretar strings como números sempre que pode.
Acontece que, por causa da intransitividade acima,
sort()
pode classificar os mesmos elementos em uma ordem diferente dependendo de sua ordem de entrada, mesmo quando não há dois elementos==
(e nenhum elemento é NAN). Eu apontei isso em um comentário para sort () , cuja essência é:fonte
sort()
tabela, também a escolhi para as implicações práticas ao escrever a postagem do blog relacionada The Greatest PHP Value . Obrigado novamente por sua resposta.usort
sempre que possível?usort($arr, 'strcmp')
. Isso funciona (para strings, é claro), mas é melhor usarsort($arr, SORT_STRING)
.