Malabarismo de tipo e comparações (estritas) de maior / menor que em PHP

115

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 > $cverdadeiro, 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.

hakre
fonte
Eu acho que você quer corrigir essa linha para ser ($a > $b) !== ($b < $a)?
Walter Tross
ah, ok, então eu entendi mal. Terei que corrigir minha resposta de acordo. Engraçado todas aquelas pessoas escrevendo tratados em vez de respostas e não lendo sua pergunta com atenção ...
Walter Tross

Respostas:

208

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 == $aseja, nem sempre é verdadeiro:

    var_dump(NAN == NAN); // bool(false)

    Nota: O fato de que qualquer comparação envolvendo NANsempre falsenã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 == $be $b == $asão sempre os mesmos.

  • Do PHP ==operador é não transitiva , ou seja, a partir $a == $be $b == $cse não se segue $a == $c:

    var_dump(true == "a"); // bool(true)
    var_dump("a" == 0);    // bool(true)
    var_dump(true == 0);   // bool(false)

Para constituir uma ordem parcial <= / >=tem que ser reflexiva, anti-simétrica e transitiva:

  • O <=operador do PHP não é reflexivo , ou $a <= $aseja, nem sempre é verdadeiro (exemplo mesmo que para ==).

  • O <=operador do PHP não é anti-simétrico , ou seja, de $a <= $be $b <= $anão segue $a == $b:

    var_dump(NAN <= "foo"); // bool(true)
    var_dump("foo" <= NAN); // bool(true)
    var_dump(NAN == "foo"); // bool(false)
  • O <=operador do PHP não é transitivo , ou seja, de $a <= $be $b <= $cnão segue $a <= $c(Exemplo igual a ==).

  • Extra: o <=operador do PHP não é total , ou seja, ambos $a <= $be $b <= $apode ser falso:

    var_dump(new stdClass <= new DateTime); // bool(false)
    var_dump(new DateTime <= new stdClass); // bool(false)

A fim de constituir uma ordem parcial estrita, < / >deve ser irreflexiva, assimétrica e transitiva:

  • O <operador do PHP é irreflexivo , ou $a < $aseja, nunca é verdadeiro. Observe que isso é verdade apenas a partir do PHP 5.4 . Anteriormente INF < INFavaliado para true.

  • O <operador do PHP não é assimétrico , ou seja, de $a < $bnão segue !($b < $a)(Exemplo igual para <=não ser anti-simétrico).

  • O <operador do PHP não é transitivo , ou seja, de $a < $be $b < $cnão segue $a < $c:

    var_dump(-INF < 0);    // bool(true)
    var_dump(0 < TRUE);    // bool(true)
    var_dump(-INF < TRUE); // bool(false)
  • Extra: o <operador do PHP não é tricotômico , ou seja, todo $a < $b, $b < $ae $a == $bpode 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 < $ce $c < $a:

    var_dump(INF < []);           // bool(true)
    var_dump([] < new stdClass);  // bool(true)
    var_dump(new stdClass < INF); // bool(true)

    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:

($a > $b) == ($b < $a)
($a >= $b) == ($b <= $a)
NikiC
fonte
2
Uau, boa resposta. Portanto, não é possível formular expressões lógicas com PHP como ($a > $b) and ($b > $c)com $a > $cmesmo que a documentação diz que aqueles </ >operadores dizem que são rigorosa ?
hakre
26
Os operadores IMHO seguem regras matemáticas, mas apenas quando lidam com os mesmos tipos de dados. A seleção de tipos é o que realmente cria confusão aqui (e em muitas outras situações). Ao comparar números e strings e conversões de tipo de valores especiais são feitas antes dos operadores, portanto, estritamente falando, os operadores de comparação não são confusos, a conversão é ...
ivanhoe
6
@ ivanhoe011 A verdade é: Ambas são :) As regras de comparação e as regras de cast do PHP são diferentes , você não pode simplesmente dizer que $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 ^^
NikiC
3
@NikiC: (int)"0xf"avalia como inteiro 0, então é claro 0 !== 15. A comparação neste exemplo se comporta exatamente como esperado. É o elenco que está confuso aqui. Admito que (INF < INF) === truefoi um problema genuíno de comparação, mas foi um caso especial e foi resolvido como você apontou. Ótima resposta .. +1
FtDRbwLXw6
1
Eu não culpo necessariamente os designers de PHP por algumas das decisões que faziam sentido sobre coerção de tipo na época ... mas eu sinto que eles deveriam ter notado os resultados dessas escolhas de design e imediatamente percebido que as escolhas estavam obviamente erradas. O exemplo mais óbvio é o comentário de @ravz.
Chade,
88

Não 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:

  1. Verifique os dois tipos de variáveis ​​com if (gettype($a) === gettype($b))
  2. Force seu tipo de elenco necessário, por exemplo. if ((string)$a === (string)$b)
  3. Force seu tipo de malabarismo necessário, por exemplo. if (($a . '') === ($b . ''))

Observe que:

  • A precisão do ponto flutuante é limitada
  • INFe NANsão do tipo floatsob
  • Alguns Infinity são iguais a outros Infinity (desde o PHP 5.4)
  • A notação científica eé sempre do tipo float, e nunca integermesmo se o número for pequeno
  • Os inteiros excedentes PHP_INT_MAXsão convertidos automaticamente parafloat
  • Flutuantes sobre os limites do sistema obtêm o INFvalor
  • Variáveis ​​indefinidas são de tipo e valor NULL
  • Inteiros precedidos por 0são convertidos de octal para decimal (por convenção)
  • A conversão de Strings contendo um inteiro com um líder 0 em tiras de um inteiro à esquerda0

Lista de algumas comparações exóticas:

Muito estranho:
     $ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b
  float (NAN) float (-INF) falso falso falso falso falso falso falso
  float (NAN) float (0) falso falso falso falso falso falso falso
  float (NAN) float (1) falso falso falso falso falso falso falso
  float (NAN) float (INF) falso falso falso falso falso falso falso
  float (NAN) float (NAN) falso falso falso falso falso falso falso
  float (NAN) int (-1) falso falso falso falso falso falso falso
  float (NAN) int (0) falso falso falso falso falso falso falso
  float (NAN) int (1) falso falso falso falso falso falso falso

Igual, mas não idêntico:

     $ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b
  NULL (NULL) array () falso falso verdadeiro verdadeiro verdadeiro falso
  NULL (NULL) bool (falso) falso falso verdadeiro verdadeiro verdadeiro falso
  NULL (NULL) float (0) falso falso verdadeiro verdadeiro verdadeiro falso
  NULL (NULL) int (0) falso falso verdadeiro verdadeiro verdadeiro falso
  NULL (NULL) str ('') falso falso verdadeiro verdadeiro verdadeiro falso
   array () bool (falso) falso falso verdadeiro verdadeiro verdadeiro falso
 bool (falso) float (0) falso falso verdadeiro verdadeiro verdadeiro falso
 bool (falso) int (0) falso falso verdadeiro verdadeiro verdadeiro falso
   str ('') bool (falso) falso falso verdadeiro verdadeiro verdadeiro falso
 bool (falso) str ('0') falso falso verdadeiro verdadeiro verdadeiro falso
 float (-INF) bool (verdadeiro) falso falso verdadeiro verdadeiro verdadeiro falso
  bool (verdadeiro) float (1) falso falso verdadeiro verdadeiro verdadeiro falso
  float (INF) bool (verdadeiro) falso falso verdadeiro verdadeiro verdadeiro falso
  float (NAN) bool (verdadeiro) falso falso verdadeiro verdadeiro verdadeiro falso
  bool (verdadeiro) int (-1) falso falso verdadeiro verdadeiro verdadeiro falso
  bool (verdadeiro) int (1) falso falso verdadeiro verdadeiro verdadeiro falso
  bool (verdadeiro) str ("\ 0") falso falso verdadeiro verdadeiro verdadeiro falso
  bool (verdadeiro) str ('+') falso falso verdadeiro verdadeiro verdadeiro falso
  bool (verdadeiro) str ('-') falso falso verdadeiro verdadeiro verdadeiro falso
  bool (verdadeiro) str ('01 ') falso falso verdadeiro verdadeiro verdadeiro falso
  bool (verdadeiro) str ('1') falso falso verdadeiro verdadeiro verdadeiro falso
  bool (verdadeiro) str ('falso') falso falso verdadeiro verdadeiro verdadeiro falso
 str ('texto') bool (verdadeiro) falso falso verdadeiro verdadeiro verdadeiro falso
 str ('verdadeiro') bool (verdadeiro) falso falso verdadeiro verdadeiro verdadeiro falso
    int (0) float (0) falso falso verdadeiro verdadeiro verdadeiro falso
  str ("\ 0") float (0) falso falso verdadeiro verdadeiro verdadeiro falso
   str ('') float (0) falso falso verdadeiro verdadeiro verdadeiro falso
   str ('+') float (0) falso falso verdadeiro verdadeiro verdadeiro falso
   str ('-') float (0) falso falso verdadeiro verdadeiro verdadeiro falso
   str ('0') float (0) falso falso verdadeiro verdadeiro verdadeiro falso
 str ('falso') float (0) falso falso verdadeiro verdadeiro verdadeiro falso
 str ('texto') float (0) falso falso verdadeiro verdadeiro verdadeiro falso
 str ('verdadeiro') float (0) falso falso verdadeiro verdadeiro verdadeiro falso
    int (1) float (1) falso falso verdadeiro verdadeiro verdadeiro falso
   float (1) str ('01 ') falso falso verdadeiro verdadeiro verdadeiro falso
   float (1) str ('1') falso falso verdadeiro verdadeiro verdadeiro falso
  str ("\ 0") int (0) falso falso verdadeiro verdadeiro verdadeiro falso
   str ('') int (0) falso falso verdadeiro verdadeiro verdadeiro falso
   str ('+') int (0) falso falso verdadeiro verdadeiro verdadeiro falso
   str ('-') int (0) falso falso verdadeiro verdadeiro verdadeiro falso
    int (0) str ('0') falso falso verdadeiro verdadeiro verdadeiro falso
 str ('falso') int (0) falso falso verdadeiro verdadeiro verdadeiro falso
 str ('texto') int (0) falso falso verdadeiro verdadeiro verdadeiro falso
 str ('verdadeiro') int (0) falso falso verdadeiro verdadeiro verdadeiro falso
    int (1) str ('01 ') falso falso verdadeiro verdadeiro verdadeiro falso
    int (1) str ('1') falso falso verdadeiro verdadeiro verdadeiro falso
   str ('1') str ('01 ') falso falso verdadeiro verdadeiro verdadeiro falso

Menor e maior ao mesmo tempo?

     $ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b
  float (NAN) str ("\ 0") verdadeiro verdadeiro verdadeiro verdadeiro falso falso
  float (NAN) str ('') verdadeiro verdadeiro verdadeiro verdadeiro falso falso
  float (NAN) str ('+') verdadeiro verdadeiro verdadeiro verdadeiro falso falso
  float (NAN) str ('-') verdadeiro verdadeiro verdadeiro verdadeiro falso falso
  float (NAN) str ('0') verdadeiro verdadeiro verdadeiro verdadeiro falso falso
  float (NAN) str ('01 ') verdadeiro verdadeiro verdadeiro verdadeiro falso falso
  float (NAN) str ('1') verdadeiro verdadeiro verdadeiro verdadeiro falso falso
  float (NAN) str ('falso') verdadeiro verdadeiro verdadeiro verdadeiro falso falso
  float (NAN) str ('texto') verdadeiro verdadeiro verdadeiro verdadeiro falso falso
  float (NAN) str ('verdadeiro') verdadeiro verdadeiro verdadeiro verdadeiro falso falso

Igual E idêntico:

     $ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b
  NULL (NULL) NULL (NULL) falso falso verdadeiro verdadeiro verdadeiro verdadeiro
 float (-INF) float (-INF) falso falso verdadeiro verdadeiro verdadeiro verdadeiro
  float (INF) float (INF) falso falso verdadeiro verdadeiro verdadeiro verdadeiro

Menor ou Maior:

     $ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b
  NULL (NULL) bool (verdadeiro) falso verdadeiro verdadeiro falso falso falso falso
 float (-INF) NULL (NULL) verdadeiro falso falso verdadeiro falso falso
  NULL (NULL) float (1) falso verdadeiro verdadeiro falso falso falso falso
  float (INF) NULL (NULL) verdadeiro falso falso verdadeiro falso falso
  float (NAN) NULL (NULL) verdadeiro falso falso verdadeiro falso falso
  NULL (NULL) int (-1) falso verdadeiro verdadeiro falso falso falso falso
  NULL (NULL) int (1) falso verdadeiro verdadeiro falso falso falso falso
  NULL (NULL) str ("\ 0") falso verdadeiro verdadeiro falso falso falso
  NULL (NULL) str ('+') falso verdadeiro verdadeiro falso falso falso falso
  NULL (NULL) str ('-') falso verdadeiro verdadeiro falso falso falso
  NULL (NULL) str ('0') falso verdadeiro verdadeiro falso falso falso falso
  NULL (NULL) str ('01 ') falso verdadeiro verdadeiro falso falso falso
  NULL (NULL) str ('1') falso verdadeiro verdadeiro falso falso falso
  NULL (NULL) str ('falso') falso verdadeiro verdadeiro falso falso falso
  NULL (NULL) str ('texto') falso verdadeiro verdadeiro falso falso falso falso
  NULL (NULL) str ('verdadeiro') falso verdadeiro verdadeiro falso falso falso falso
   array () bool (verdadeiro) falso verdadeiro verdadeiro falso falso falso falso
 float (-INF) array () falso verdadeiro verdadeiro falso falso falso falso
   array () float (0) verdadeiro falso falso verdadeiro falso falso
   array () float (1) verdadeiro falso falso verdadeiro falso falso
  float (INF) array () falso verdadeiro verdadeiro falso falso falso falso
  float (NAN) array () falso verdadeiro verdadeiro falso falso falso falso
   array () int (-1) verdadeiro falso falso verdadeiro falso falso
   array () int (0) verdadeiro falso falso verdadeiro falso falso
   array () int (1) verdadeiro falso falso verdadeiro falso falso
   array () str ("\ 0") verdadeiro falso falso verdadeiro falso falso
   str ('') array () falso verdadeiro verdadeiro falso falso falso falso
   array () str ('+') verdadeiro falso falso verdadeiro falso falso
   array () str ('-') verdadeiro falso falso verdadeiro falso falso
   array () str ('0') verdadeiro falso falso verdadeiro falso falso
   array () str ('01 ') verdadeiro falso falso verdadeiro falso falso
   array () str ('1') verdadeiro falso falso verdadeiro falso falso
   array () str ('false') verdadeiro falso falso verdadeiro falso falso
   array () str ('texto') verdadeiro falso falso verdadeiro falso falso
   array () str ('verdadeiro') verdadeiro falso falso verdadeiro falso falso
  bool (verdadeiro) bool (falso) verdadeiro falso falso verdadeiro falso falso
 float (-INF) bool (falso) verdadeiro falso falso verdadeiro falso falso
   float (1) bool (falso) verdadeiro falso falso verdadeiro falso falso
  float (INF) bool (falso) verdadeiro falso falso verdadeiro falso falso
  float (NAN) bool (falso) verdadeiro falso falso verdadeiro falso falso
 bool (falso) int (-1) falso verdadeiro verdadeiro falso falso falso falso
    int (1) bool (falso) verdadeiro falso falso verdadeiro falso falso
 bool (falso) str ("\ 0") falso verdadeiro verdadeiro falso falso falso falso
 bool (falso) str ('+') falso verdadeiro verdadeiro falso falso falso falso
 bool (falso) str ('-') falso verdadeiro verdadeiro falso falso falso falso
 bool (falso) str ('01 ') falso verdadeiro verdadeiro falso falso falso falso
   str ('1') bool (falso) verdadeiro falso falso verdadeiro falso falso
 bool (falso) str ('falso') falso verdadeiro verdadeiro falso falso falso falso
 str ('texto') bool (falso) verdadeiro falso falso verdadeiro falso falso
 str ('verdadeiro') bool (falso) verdadeiro falso falso verdadeiro falso falso
  bool (verdadeiro) float (0) verdadeiro falso falso verdadeiro falso falso
  bool (verdadeiro) int (0) verdadeiro falso falso verdadeiro falso falso
   str ('') bool (verdadeiro) falso verdadeiro verdadeiro falso falso falso falso
  bool (verdadeiro) str ('0') verdadeiro falso falso verdadeiro falso falso
 float (-INF) float (0) falso verdadeiro verdadeiro falso falso falso
 float (-INF) float (1) falso verdadeiro verdadeiro falso falso falso falso
  float (INF) float (-INF) verdadeiro falso falso verdadeiro falso falso
 float (-INF) int (-1) falso verdadeiro verdadeiro falso falso falso
 float (-INF) int (0) falso verdadeiro verdadeiro falso falso falso falso
 float (-INF) int (1) falso verdadeiro verdadeiro falso falso falso
 float (-INF) str ("\ 0") falso verdadeiro verdadeiro falso falso falso falso
 float (-INF) str ('') falso verdadeiro verdadeiro falso falso falso falso
 float (-INF) str ('+') falso verdadeiro verdadeiro falso falso falso
 float (-INF) str ('-') falso verdadeiro verdadeiro falso falso falso falso
 float (-INF) str ('0') falso verdadeiro verdadeiro falso falso falso
 float (-INF) str ('01 ') falso verdadeiro verdadeiro falso falso falso falso
 float (-INF) str ('1') falso verdadeiro verdadeiro falso falso falso
 float (-INF) str ('falso') falso verdadeiro verdadeiro falso falso falso
 float (-INF) str ('texto') falso verdadeiro verdadeiro falso falso falso
 float (-INF) str ('verdadeiro') falso verdadeiro verdadeiro falso falso falso
   float (1) float (0) verdadeiro falso falso verdadeiro falso falso
  float (INF) float (0) verdadeiro falso falso verdadeiro falso falso
   float (0) int (-1) verdadeiro falso falso verdadeiro falso falso
    int (1) float (0) verdadeiro falso falso verdadeiro falso falso
   float (0) str ('01 ') falso verdadeiro verdadeiro falso falso falso falso
   str ('1') float (0) verdadeiro falso falso verdadeiro falso falso
  float (INF) float (1) verdadeiro falso falso verdadeiro falso falso
   float (1) int (-1) verdadeiro falso falso verdadeiro falso falso
   float (1) int (0) verdadeiro falso falso verdadeiro falso falso
   float (1) str ("\ 0") verdadeiro falso falso verdadeiro falso falso
   str ('') float (1) falso verdadeiro verdadeiro falso falso falso falso
   float (1) str ('+') verdadeiro falso falso verdadeiro falso falso
   float (1) str ('-') verdadeiro falso falso verdadeiro falso falso
   float (1) str ('0') verdadeiro falso falso verdadeiro falso falso
   float (1) str ('falso') verdadeiro falso falso verdadeiro falso falso
 str ('texto') float (1) falso verdadeiro verdadeiro falso falso falso falso
 str ('verdadeiro') float (1) falso verdadeiro verdadeiro falso falso falso falso
  float (INF) int (-1) verdadeiro falso falso verdadeiro falso falso
  float (INF) int (0) verdadeiro falso falso verdadeiro falso falso
  float (INF) int (1) verdadeiro falso falso verdadeiro falso falso
  float (INF) str ("\ 0") verdadeiro falso falso verdadeiro falso falso
  float (INF) str ('') verdadeiro falso falso verdadeiro falso falso
  float (INF) str ('+') verdadeiro falso falso verdadeiro falso falso
  float (INF) str ('-') verdadeiro falso falso verdadeiro falso falso
  float (INF) str ('0') verdadeiro falso falso verdadeiro falso falso
  float (INF) str ('01 ') verdadeiro falso falso verdadeiro falso falso
  float (INF) str ('1') verdadeiro falso falso verdadeiro falso falso
  float (INF) str ('false') verdadeiro falso falso verdadeiro falso falso
  float (INF) str ('texto') verdadeiro falso falso verdadeiro falso falso
  float (INF) str ('verdadeiro') verdadeiro falso falso verdadeiro falso falso
    int (0) int (-1) verdadeiro falso falso verdadeiro falso falso
    int (1) int (-1) verdadeiro falso falso verdadeiro falso falso
  str ("\ 0") int (-1) verdadeiro falso falso verdadeiro falso falso
   str ('') int (-1) verdadeiro falso falso verdadeiro falso falso
   str ('+') int (-1) verdadeiro falso falso verdadeiro falso falso
   str ('-') int (-1) verdadeiro falso falso verdadeiro falso falso
   str ('0') int (-1) verdadeiro falso falso verdadeiro falso falso
   int (-1) str ('01 ') falso verdadeiro verdadeiro falso falso falso falso
   str ('1') int (-1) verdadeiro falso falso verdadeiro falso falso
 str ('falso') int (-1) verdadeiro falso falso verdadeiro falso falso
 str ('texto') int (-1) verdadeiro falso falso verdadeiro falso falso
 str ('verdadeiro') int (-1) verdadeiro falso falso verdadeiro falso falso
    int (1) int (0) verdadeiro falso falso verdadeiro falso falso
    int (0) str ('01 ') falso verdadeiro verdadeiro falso falso falso falso
   str ('1') int (0) verdadeiro falso falso verdadeiro falso falso
    int (1) str ("\ 0") verdadeiro falso falso verdadeiro falso falso
   str ('') int (1) falso verdadeiro verdadeiro falso falso falso falso
    int (1) str ('+') verdadeiro falso falso verdadeiro falso falso
    int (1) str ('-') verdadeiro falso falso verdadeiro falso falso
    int (1) str ('0') verdadeiro falso falso verdadeiro falso falso
    int (1) str ('falso') verdadeiro falso falso verdadeiro falso falso
 str ('texto') int (1) falso verdadeiro verdadeiro falso falso falso falso
 str ('verdadeiro') int (1) falso verdadeiro verdadeiro falso falso falso falso
   str ('') str ("\ 0") falso verdadeiro verdadeiro falso falso falso
   str ('+') str ("\ 0") verdadeiro falso falso verdadeiro falso falso
   str ('-') str ("\ 0") verdadeiro falso falso verdadeiro falso falso
  str ("\ 0") str ('0') falso verdadeiro verdadeiro falso falso falso falso
  str ("\ 0") str ('01 ') falso verdadeiro verdadeiro falso falso falso falso
   str ('1') str ("\ 0") verdadeiro falso falso verdadeiro falso falso
 str ('falso') str ("\ 0") verdadeiro falso falso verdadeiro falso falso
 str ('texto') str ("\ 0") verdadeiro falso falso verdadeiro falso falso
 str ('verdadeiro') str ("\ 0") verdadeiro falso falso verdadeiro falso falso
   str ('') str ('+') falso verdadeiro verdadeiro falso falso falso falso
   str ('') str ('-') falso verdadeiro verdadeiro falso falso falso falso
   str ('') str ('0') falso verdadeiro verdadeiro falso falso falso
   str ('') str ('01 ') falso verdadeiro verdadeiro falso falso falso falso
   str ('') str ('1') falso verdadeiro verdadeiro falso falso falso falso
   str ('') str ('falso') falso verdadeiro verdadeiro falso falso falso falso
   str ('') str ('texto') falso verdadeiro verdadeiro falso falso falso
   str ('') str ('verdadeiro') falso verdadeiro verdadeiro falso falso falso falso
   str ('-') str ('+') verdadeiro falso falso verdadeiro falso falso
   str ('+') str ('0') falso verdadeiro verdadeiro falso falso falso
   str ('+') str ('01 ') falso verdadeiro verdadeiro falso falso falso
   str ('1') str ('+') verdadeiro falso falso verdadeiro falso falso
 str ('falso') str ('+') verdadeiro falso falso verdadeiro falso falso
 str ('texto') str ('+') verdadeiro falso falso verdadeiro falso falso
 str ('verdadeiro') str ('+') verdadeiro falso falso verdadeiro falso falso
   str ('-') str ('0') falso verdadeiro verdadeiro falso falso falso falso
   str ('-') str ('01 ') falso verdadeiro verdadeiro falso falso falso falso
   str ('1') str ('-') verdadeiro falso falso verdadeiro falso falso
 str ('falso') str ('-') verdadeiro falso falso verdadeiro falso falso
 str ('texto') str ('-') verdadeiro falso falso verdadeiro falso falso
 str ('verdadeiro') str ('-') verdadeiro falso falso verdadeiro falso falso
   str ('0') str ('01 ') falso verdadeiro verdadeiro falso falso falso
   str ('1') str ('0') verdadeiro falso falso verdadeiro falso falso
 str ('falso') str ('0') verdadeiro falso falso verdadeiro falso falso
 str ('texto') str ('0') verdadeiro falso falso verdadeiro falso falso
 str ('verdadeiro') str ('0') verdadeiro falso falso verdadeiro falso falso
 str ('falso') str ('01 ') verdadeiro falso falso verdadeiro falso falso
 str ('texto') str ('01 ') verdadeiro falso falso verdadeiro falso falso
 str ('verdadeiro') str ('01 ') verdadeiro falso falso verdadeiro falso falso
   str ('1') str ('falso') falso verdadeiro verdadeiro falso falso falso
 str ('texto') str ('1') verdadeiro falso falso verdadeiro falso falso
 str ('verdadeiro') str ('1') verdadeiro falso falso verdadeiro falso falso
 str ('texto') str ('falso') verdadeiro falso falso verdadeiro falso falso
 str ('verdadeiro') str ('falso') verdadeiro falso falso verdadeiro falso falso
 str ('verdadeiro') str ('texto') verdadeiro falso falso verdadeiro falso falso

$a > $b > $cEnigma quando: $anão é maior que $c.

A <C: float (NAN)> str ('a')> str ('')
A <C: float (NAN)> str ('a')> str ('1')
A <C: float (NAN)> str ('a')> str ('A')
A <C: float (NAN)> str ('a')> str ('0')
A <C: float (NAN)> str ('1')> str ('')
A <C: float (NAN)> str ('1')> str ('0')
A <C: float (NAN)> str ('A')> str ('')
A <C: float (NAN)> str ('A')> str ('1')
A <C: float (NAN)> str ('A')> str ('0')
A <C: float (NAN)> str ('0')> str ('')
A <C: str ('')> float (NAN)> str ('a')
A <C: str ('')> float (NAN)> str ('1')
A <C: str ('')> float (NAN)> str ('A')
A <C: str ('')> float (NAN)> str ('0')
A <C: str ('a')> str ('')> flutuante (NAN)
A <C: str ('a')> str ('1')> flutuante (NAN)
A <C: str ('a')> str ('A')> float (NAN)
A <C: str ('a')> str ('0')> float (NAN)
A <C: str ('0')> str ('')> flutuante (NAN)
A == C: bool (true)> str ('')> float (NAN)
A == C: bool (true)> str ('')> float (-INF)
A == C: bool (true)> str ('')> int (-1)
A == C: bool (true)> str ('')> float (-1)
A == C: bool (true)> array ()> float (NAN)
A == C: bool (true)> array ()> float (INF)
A == C: bool (true)> array ()> float (-INF)
A == C: bool (true)> array ()> str ('a')
A == C: bool (true)> array ()> int (1)
A == C: bool (true)> array ()> float (1)
A == C: bool (true)> array ()> str ('1')
A == C: bool (true)> array ()> str ('A')
A == C: bool (true)> array ()> int (-1)
A == C: bool (true)> array ()> float (-1)
A == C: bool (true)> int (0)> float (-INF)
A == C: bool (verdadeiro)> int (0)> int (-1)
A == C: bool (verdadeiro)> int (0)> float (-1)
A == C: bool (true)> str ('0')> float (NAN)
A == C: bool (true)> str ('0')> float (-INF)
A == C: bool (verdadeiro)> str ('0')> int (-1)
A == C: bool (true)> str ('0')> float (-1)
A == C: bool (true)> float (0)> float (-INF)
A == C: bool (verdadeiro)> float (0)> int (-1)
A == C: bool (verdadeiro)> float (0)> float (-1)
A == C: int (1)> str ('a')> str ('1')
A == C: int (1)> str ('A')> str ('1')
A == C: float (1)> str ('a')> str ('1')
A == C: float (1)> str ('A')> str ('1')
A == C: str ('a')> str ('1')> int (0)
A == C: str ('a')> str ('1')> float (0)
A == C: str ('')> float (-INF)> NULL (NULL)
A == C: str ('')> float (-INF)> bool (falso)
A == C: str ('')> int (-1)> NULL (NULL)
A == C: str ('')> int (-1)> bool (falso)
A == C: str ('')> float (-1)> NULL (NULL)
A == C: str ('')> float (-1)> bool (falso)
A == C: array ()> float (NAN)> NULL (NULL)
A == C: array ()> float (NAN)> bool (false)
A == C: array ()> float (INF)> NULL (NULL)
A == C: array ()> float (INF)> bool (falso)
A == C: array ()> float (-INF)> NULL (NULL)
A == C: array ()> float (-INF)> bool (falso)
A == C: array ()> str ('a')> NULL (NULL)
A == C: array ()> str ('a')> bool (falso)
A == C: array ()> int (1)> NULL (NULL)
A == C: array ()> int (1)> bool (falso)
A == C: array ()> float (1)> NULL (NULL)
A == C: array ()> float (1)> bool (falso)
A == C: array ()> str ('1')> NULL (NULL)
A == C: array ()> str ('1')> bool (falso)
A == C: array ()> str ('A')> NULL (NULL)
A == C: array ()> str ('A')> bool (falso)
A == C: array ()> str ('0')> NULL (NULL)
A == C: array ()> int (-1)> NULL (NULL)
A == C: array ()> int (-1)> bool (falso)
A == C: array ()> float (-1)> NULL (NULL)
A == C: array ()> float (-1)> bool (falso)
A == C: str ('')> float (NAN)> bool (falso)
A == C: str ('')> float (NAN)> NULL (NULL)
A == C: str ('A')> str ('1')> int (0)
A == C: str ('A')> str ('1')> float (0)
A == C: int (0)> float (-INF)> NULL (NULL)
A == C: int (0)> float (-INF)> bool (falso)
A == C: int (0)> int (-1)> NULL (NULL)
A == C: int (0)> int (-1)> bool (falso)
A == C: int (0)> float (-1)> NULL (NULL)
A == C: int (0)> float (-1)> bool (falso)
A == C: str ('0')> float (NAN)> bool (falso)
A == C: str ('0')> float (-INF)> bool (falso)
A == C: str ('0')> int (-1)> bool (falso)
A == C: str ('0')> float (-1)> bool (falso)
A == C: float (0)> float (-INF)> NULL (NULL)
A == C: float (0)> float (-INF)> bool (falso)
A == C: float (0)> int (-1)> NULL (NULL)
A == C: float (0)> int (-1)> bool (falso)
A == C: float (0)> float (-1)> NULL (NULL)
A == C: float (0)> float (-1)> bool (falso)
A === C: str ('0')> float (NAN)> str ('0')
A === C: str ('')> float (NAN)> str ('')
A === C: str ('a')> float (NAN)> str ('a')
A === C: str ('1')> float (NAN)> str ('1')
A === C: str ('A')> float (NAN)> str ('A')

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() e is_null()
  • if() e empty()
  • booleano ==vs.===

Verifique as diferenças entre as versões do PHP ao vivo em. http://3v4l.org/MAfDu .

CSᵠ
fonte
26
+1, sem falar nas "tabelas" roláveis ​​com cabeçalhos de coluna fixa - ideia bacana;)
hakre
É necessário usar um operador estrito ao criar um tipo? Quer dizer, você escreveu, if ( (string)$a===(string)$b )mas não é exatamente o mesmo que if ( (string)$a==(string)$b )?
Voitcus
@Voitcus yes para type-cast (string)1==(string)'01'-> bool(true)e para type-juggle (1 . '')=='01'-> bool(true)não exatamente o mesmo que ===quando você receberia bool(false)em ambas as contas
CSᵠ
1
Um detalhe: os valores octais não são "convertidos na atribuição", eles são interpretados pelo compilador, que tem que transformar o ASCII em números binários reais.
IMSoP
INFINITY is equal to INFINITY which is mathematically incorrect!é uma declaração decididamente discutível. Observe também que NaNé por convenção não maior, menor ou igual a qualquer coisa em qualquer linguagem de programação que eu conheça.
DaveRandom de
22

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:

"10" < "1a"
"1a" < "2"
"10" > "2"

Se <fosse transitivo ( $a < $b$b < $c$a < $c), a última linha seria

"10" < "2"

mas 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 é:

sort(array("10", "1a", "2" )) => array("10", "1a", "2" )
sort(array("10", "2",  "1a")) => array("1a", "2",  "10")
sort(array("1a", "10", "2" )) => array("2",  "10", "1a")
sort(array("1a", "2",  "10")) => array("1a", "2",  "10")
sort(array("2",  "10", "1a")) => array("2",  "10", "1a")
sort(array("2",  "1a", "10")) => array("10", "1a", "2" )
Walter Tross
fonte
1
o comentário anterior se refere a uma parte da resposta (relacionada à segunda parte da pergunta) que excluí entretanto
Walter Tross
Removido agora;) E uma bela nova 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.
hakre,
Isso significa que se deve usar usortsempre que possível?
Voitcus
2
@Voitcus: Acho que você quer dizer usort($arr, 'strcmp'). Isso funciona (para strings, é claro), mas é melhor usar sort($arr, SORT_STRING).
Walter Tross,
@WalterTross, quero dizer, sempre use sua própria função (não apenas para strings) para garantir que esteja sempre correta
Voitcus,