Malabarismo de tipos y (estricto) comparaciones mayor / menor que en PHP

115

PHP es famoso por su malabarismo de tipos. Debo admitir que me desconcierta, y estoy teniendo dificultades para descubrir cosas lógicas / fundamentales básicas en las comparaciones.

Por ejemplo: si $a > $bes verdadero y $b > $ces verdadero, ¿debe significar que siempre$a > $c es verdad también?

Siguiendo la lógica básica, diría que sí. pero estoy tan desconcertado de que no confío realmente en PHP en esto. ¿Quizás alguien pueda dar un ejemplo en el que este no sea el caso?

También me pregunto con los operadores estrictos menor que y estricto mayor que (ya que su significado se describe como estrictamente que solo sabía en el pasado por las comparaciones de igualdad) si hay alguna diferencia si los operandos izquierdo y derecho se intercambian con valores estrictamente desiguales:

# Precondition:
if ($a === $b) {
    throw new Exception(
       'Both are strictly equal - can not compare strictly for greater or smaller'
    );
}

($a > $b) !== ($b > $a)

Para la mayoría de las combinaciones de comparación de tipos, estos operadores de comparación mayor / menor no están documentados, por lo que leer el manual no fue realmente útil en este caso.

hakre
fuente
¿Supongo que quieres corregir esa línea para que sea ($a > $b) !== ($b < $a)?
Walter Tross
ah, ok, lo entendí mal. Tendré que arreglar mi respuesta en consecuencia. Es curioso que todas esas personas escriban tratados en lugar de respuestas y no lean tu pregunta con atención ...
Walter Tross

Respuestas:

208

Los operadores de comparación de PHP se desvían de las definiciones informáticas científicas de varias formas:

Para constituir una relación de equivalencia == tiene que ser reflexiva, simétrica y transitiva:

  • El ==operador de PHP no es reflexivo , $a == $aes decir, no siempre es cierto:

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

    Nota: El hecho de que cualquier comparación que involucre NANsiempre falseno es específico de PHP. Es un mandato del estándar IEEE 754 para aritmética de punto flotante ( más información ).

  • El ==operador de PHP es simétrico , es decir, $a == $by $b == $ason siempre iguales.

  • PHP ==operador es no transitiva , es decir, desde $a == $by $b == $cqué no sigue $a == $c:

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

Para constituir un orden parcial <= / >=tiene que ser reflexivo, antisimétrico y transitivo:

  • El <=operador de PHP no es reflexivo , $a <= $aes decir, no siempre es cierto (el ejemplo es el mismo que para ==).

  • El <=operador de PHP no es anti-simétrico , es decir, de $a <= $by $b <= $ano sigue $a == $b:

    var_dump(NAN <= "foo"); // bool(true)
    var_dump("foo" <= NAN); // bool(true)
    var_dump(NAN == "foo"); // bool(false)
  • El <=operador de PHP no es transitivo , es decir, de $a <= $by $b <= $cno sigue $a <= $c(el mismo ejemplo que para ==).

  • Extra: el <=operador de PHP no es total , es decir, ambos $a <= $by $b <= $apuede ser falso:

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

Para constituir un orden parcial estricto < / >tiene que ser irreflexivo, asimétrico y transitivo:

  • El <operador de PHP es irreflexivo , $a < $aes decir, nunca es cierto. Tenga en cuenta que esto es cierto solo a partir de PHP 5.4 . INF < INFEvaluado previamente a true.

  • El <operador de PHP no es asimétrico , es decir, de $a < $bno sigue !($b < $a)(ejemplo igual que para <=no ser antisimétrico).

  • El <operador de PHP no es transitivo , es decir, de $a < $by $b < $cno sigue $a < $c:

    var_dump(-INF < 0);    // bool(true)
    var_dump(0 < TRUE);    // bool(true)
    var_dump(-INF < TRUE); // bool(false)
  • Extra: El <operador de PHP no es tricotómico , es decir, todo $a < $b, $b < $ay $a == $bpuede ser falso (Ejemplo igual que para <=no ser total).

  • Extra: el <operador de PHP puede ser circular , es decir, es posible que $a < $b, $b < $cy $c < $a:

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

    Nota: El ejemplo anterior arroja un aviso de "Objeto de clase stdClass no se pudo convertir en doble".

Puede encontrar algunos buenos gráficos para los operadores de comparación de PHP en PHP Sadness 52 - Operadores de comparación .

Como última nota, quiero señalar que hay dos igualdades que hace PHP garantía (a diferencia de casi todo lo demás). Estos dos siempre se mantienen, simplemente porque el compilador reduce uno al otro:

($a > $b) == ($b < $a)
($a >= $b) == ($b <= $a)
NikiC
fuente
2
Vaya, buena respuesta. Entonces, ¿no es posible formular expresiones lógicas con PHP como ($a > $b) and ($b > $c)con $a > $caunque la documentación dice que esos operadores </ >dicen que son estrictos ?
hakre
26
En mi humilde opinión, los operadores siguen las reglas matemáticas, pero solo cuando se trata de los mismos tipos de datos. La conversión de tipos es lo que realmente crea la confusión aquí (y en muchas otras situaciones). Cuando se comparan números, cadenas y valores especiales, las conversiones de tipos se realizan antes que los operadores, por lo que, estrictamente hablando, los operadores de comparación no son confusos, la conversión es ...
ivanhoe
6
@ ivanhoe011 La verdad es: Ambos son :) Las reglas de comparación de PHP y las reglas de conversión de PHP son diferentes , no se puede simplemente decir que $a == $bes lo mismo que (type) $a === (type) $b. Un simple ejemplo de esto es eso "15" == "0xf", pero (int) "15" !== (int) "0xf". Y tanto la comparación como las reglas de conversión en PHP son totalmente locas ^^
NikiC
3
@NikiC: (int)"0xf"evalúa a un número entero 0, por supuesto 0 !== 15. La comparación en este ejemplo se comporta exactamente como se esperaba. Es el casting lo que confunde aquí. Lo admito, (INF < INF) === truefue un problema de comparación genuino, pero fue un caso especial, y se resolvió como usted señaló. Excelente respuesta ... +1
FtDRbwLXw6
1
No necesariamente culpo a los diseñadores de PHP por algunas de las decisiones que tenían sentido sobre la coerción de tipos en ese momento ... pero siento que deberían haber notado los resultados de estas elecciones de diseño e inmediatamente darme cuenta de que las elecciones eran obviamente incorrectas. El ejemplo más obvio es el comentario de @ravz.
Chad
88

No hay operadores de comparación estrictamente idénticos ( >==o <==) en PHP (por PHP 5.6.14 al menos) , pero hay algunas formas de hacer cumplir una verificación de tipo estricta antes de marcar Mayor / Inferior:

  1. Marque ambos tipos de variables con if (gettype($a) === gettype($b))
  2. Fuerza el tipo de conversión necesario, por ejemplo. if ((string)$a === (string)$b)
  3. Fuerza tu tipo de malabarismo necesario, por ejemplo. if (($a . '') === ($b . ''))

Toma nota de que:

  • La precisión del punto flotante es limitada
  • INFy NANson de tipofloat bajo
  • Algunos Infinity equivalen a otros Infinity (desde PHP 5.4)
  • La notación científica ees siempre de tipo floaty nunca, integerincluso si el número es pequeño
  • Los enteros que se superan PHP_INT_MAXse convierten automáticamente enfloat
  • Flota sobre los límites del sistema INF valor
  • Las variables indefinidas son de tipo y valor NULL
  • Enteros precedidos por 0 se convierten de octal a decimal (por convención)
  • La conversión de cadenas que contienen un número entero con un encabezado 0 a un número entero elimina el encabezado0

Lista de algunas comparaciones exóticas:

Muy extraño:
     $ 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
  float (NAN) float (0) falso falso falso falso falso falso
  float (NAN) float (1) falso falso falso falso falso falso
  float (NAN) float (INF) falso falso falso falso falso falso
  float (NAN) float (NAN) falso falso falso falso falso falso
  float (NAN) int (-1) falso falso falso falso falso falso
  float (NAN) int (0) falso falso falso falso falso falso
  float (NAN) int (1) falso falso falso falso falso falso

Igual pero no idéntico:

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

¿Más bajo y más grande al mismo tiempo?

     $ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b
  float (NAN) str ("\ 0") verdadero verdadero verdadero verdadero falso falso
  float (NAN) str ('') verdadero verdadero verdadero verdadero falso falso
  float (NAN) str ('+') verdadero verdadero verdadero verdadero falso falso
  float (NAN) str ('-') verdadero verdadero verdadero verdadero falso falso
  float (NAN) str ('0') verdadero verdadero verdadero verdadero falso falso
  float (NAN) str ('01 ') verdadero verdadero verdadero verdadero falso falso
  float (NAN) str ('1') verdadero verdadero verdadero verdadero falso falso
  float (NAN) str ('falso') verdadero verdadero verdadero verdadero falso falso
  float (NAN) str ('texto') verdadero verdadero verdadero verdadero falso falso
  float (NAN) str ('verdadero') verdadero verdadero verdadero verdadero 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 verdadero verdadero verdadero verdadero
 float (-INF) float (-INF) falso falso verdadero verdadero verdadero verdadero
  float (INF) float (INF) falso falso verdadero verdadero verdadero verdadero

Menor o mayor:

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

$a > $b > $cEnigma cuando: $ano es mayor 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 ('')> float (NAN)
A <C: str ('a')> str ('1')> float (NAN)
A <C: str ('a')> str ('A')> float (NAN)
A <C: str ('a')> str ('0')> float (NAN)
A <C: str ('0')> str ('')> float (NAN)
A == C: bool (verdadero)> str ('')> float (NAN)
A == C: bool (verdadero)> str ('')> float (-INF)
A == C: bool (verdadero)> str ('')> int (-1)
A == C: bool (verdadero)> str ('')> float (-1)
A == C: bool (verdadero)> matriz ()> flotante (NAN)
A == C: bool (verdadero)> matriz ()> flotante (INF)
A == C: bool (verdadero)> matriz ()> flotante (-INF)
A == C: bool (verdadero)> matriz ()> str ('a')
A == C: bool (verdadero)> matriz ()> int (1)
A == C: bool (verdadero)> matriz ()> flotante (1)
A == C: bool (verdadero)> matriz ()> str ('1')
A == C: bool (verdadero)> matriz ()> str ('A')
A == C: bool (verdadero)> matriz ()> int (-1)
A == C: bool (verdadero)> matriz ()> flotante (-1)
A == C: bool (verdadero)> int (0)> float (-INF)
A == C: bool (verdadero)> int (0)> int (-1)
A == C: bool (verdadero)> int (0)> float (-1)
A == C: bool (verdadero)> str ('0')> float (NAN)
A == C: bool (verdadero)> str ('0')> float (-INF)
A == C: bool (verdadero)> str ('0')> int (-1)
A == C: bool (verdadero)> str ('0')> float (-1)
A == C: bool (verdadero)> float (0)> float (-INF)
A == C: bool (verdadero)> float (0)> int (-1)
A == C: bool (verdadero)> flotar (0)> flotar (-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: matriz ()> flotante (NAN)> NULL (NULL)
A == C: matriz ()> flotante (NAN)> bool (falso)
A == C: matriz ()> flotante (INF)> NULL (NULL)
A == C: matriz ()> flotante (INF)> bool (falso)
A == C: matriz ()> float (-INF)> NULL (NULL)
A == C: matriz ()> flotante (-INF)> bool (falso)
A == C: matriz ()> str ('a')> NULL (NULL)
A == C: matriz ()> str ('a')> bool (falso)
A == C: matriz ()> int (1)> NULL (NULL)
A == C: matriz ()> int (1)> bool (falso)
A == C: matriz ()> float (1)> NULL (NULL)
A == C: matriz ()> float (1)> bool (falso)
A == C: matriz ()> str ('1')> NULL (NULL)
A == C: matriz ()> str ('1')> bool (falso)
A == C: matriz ()> str ('A')> NULL (NULL)
A == C: matriz ()> str ('A')> bool (falso)
A == C: matriz ()> str ('0')> NULL (NULL)
A == C: matriz ()> int (-1)> NULL (NULL)
A == C: matriz ()> int (-1)> bool (falso)
A == C: matriz ()> float (-1)> NULL (NULL)
A == C: matriz ()> flotante (-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')> flotar (NAN)> str ('1')
A === C: str ('A')> float (NAN)> str ('A')

Divertida comparación de cuerdas: 'Queen' >'King' >'Jack' >'Ace'

Consulte también las tablas de comparación de tipos de PHP que cubren pares:

  • isset() y is_null()
  • if() y empty()
  • booleano ==vs.===

Compruebe las diferencias entre las versiones de PHP en vivo en. http://3v4l.org/MAfDu .

CSᵠ
fuente
26
+1 y mucho menos las "tablas" desplazables con los encabezados de columna fija - idea ingeniosa;)
hakre
¿Es necesario utilizar un operador estricto al realizar la fundición? Quiero decir que has escrito, if ( (string)$a===(string)$b )pero ¿no es exactamente lo mismo que if ( (string)$a==(string)$b )?
Voitcus
@Voitcus sí para type-cast (string)1==(string)'01'-> bool(true)y type-juggle (1 . '')=='01'-> bool(true)no es exactamente lo mismo que ===cuando obtendría bool(false)ambas cuentas
CSᵠ
1
Un detalle: los valores octales no se "convierten en asignación", son interpretados por el compilador, que tiene que convertir ASCII en números binarios reales.
IMSoP
INFINITY is equal to INFINITY which is mathematically incorrect!es una declaración decididamente discutible. También tenga en cuenta que NaNes por convención no mayor, menor o igual a cualquier cosa en cualquier lenguaje de programación que yo sepa.
DaveRandom
22

Después de corregir la segunda parte de su pregunta, dejo la respuesta a esa parte a los demás. Solo quiero dar la respuesta más sorprendente a la primera parte de su pregunta, es decir, si hay un ejemplo de que los operadores <y >son intransitivos. Aquí está.

Estos son todos true:

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

Si <fuera transitivo ( $a < $b$b < $c$a < $c), la última línea sería

"10" < "2"

pero PHP intenta ser amable (?!) e interpretar cadenas como números siempre que puede.

Resulta que, debido a la intransibilidad anterior, se sort()pueden clasificar los mismos elementos en un orden diferente dependiendo de su orden de entrada, incluso cuando no hay dos elementos== (y ningún elemento es NAN). Señalé esto en un comentario para sort () , cuya esencia es:

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
fuente
1
el comentario anterior se refiere a una parte de la respuesta (relacionada con la segunda parte de la pregunta) que he eliminado mientras tanto
Walter Tross
Eliminado eso ahora;) Y una buena sort()tabla nueva , la elegí también por las implicaciones prácticas al escribir la publicación de blog relacionada The Greatest PHP Value . Gracias de nuevo por su respuesta.
hakre
¿Significa que se debe usar usortsiempre que sea posible?
Voitcus
2
@Voitcus: Supongo que te refieres usort($arr, 'strcmp'). Esto funciona (para cadenas, por supuesto), pero es mejor usarlo sort($arr, SORT_STRING).
Walter Tross
@WalterTross Me refiero a que siempre use su propia función (no solo para cadenas) para asegurarse de que siempre sea correcta
Voitcus