Type-juggling e confronti (rigorosi) maggiore / minore di in PHP


115

PHP è famoso per il suo tipo di giocoleria. Devo ammettere che mi lascia perplesso e ho difficoltà a scoprire le cose logiche / fondamentali di base nei confronti.

Ad esempio: se $a > $bè vero ed $b > $cè vero, deve significare anche che $a > $cè sempre vero?

Seguendo la logica di base, direi di sì, ma sono così perplesso di non fidarmi davvero di PHP in questo. Forse qualcuno può fornire un esempio in cui questo non è il caso?

Inoltre mi chiedo con gli operatori rigoroso minore di e rigoroso maggiore di (poiché il loro significato è descritto come strettamente che conoscevo solo in passato dai confronti di uguaglianza) se fa qualche differenza se gli operandi sinistro e destro vengono scambiati con valori rigorosamente disuguali:

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

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

Per la maggior parte di tutte le combinazioni di confronto dei tipi questi operatori di confronto maggiore / minore non sono documentati, quindi la lettura del manuale non è stata di grande aiuto in questo caso.


Immagino tu voglia correggere quella riga in modo che sia ($a > $b) !== ($b < $a)?
Walter Tross

ah, ok, quindi l'ho capito male. Dovrò correggere la mia risposta di conseguenza. Divertente tutte quelle persone che scrivono trattati invece di risposte e non leggono attentamente la tua domanda ...
Walter Tross

Risposte:


208

Gli operatori di confronto di PHP si discostano dalle definizioni computer-scientifiche in diversi modi:

Per costituire una relazione di equivalenza == deve essere riflessiva, simmetrica e transitiva:

  • L' ==operatore di PHP non è riflessivo , ovvero $a == $anon è sempre vero:

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

    Nota: il fatto che qualsiasi confronto che coinvolge NANsia sempre falsenon è specifico di PHP. È imposto dallo standard IEEE 754 per l'aritmetica in virgola mobile ( maggiori informazioni ).

  • L' ==operatore di PHP è simmetrico , cioè $a == $be $b == $asono sempre gli stessi.

  • Di PHP ==operatore non è transitiva , cioè da $a == $be $b == $cnon non segue $a == $c:

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

Per costituire un ordine parziale <= / >=deve essere riflessivo, antisimmetrico e transitivo:

  • L' <=operatore di PHP non è riflessivo , cioè $a <= $anon è sempre vero (Esempio uguale a ==).

  • L' <=operatore di PHP non è antisimmetrico , cioè da $a <= $be $b <= $anon segue $a == $b:

    var_dump(NAN <= "foo"); // bool(true)
    var_dump("foo" <= NAN); // bool(true)
    var_dump(NAN == "foo"); // bool(false)
  • L' <=operatore di PHP non è transitivo , cioè da $a <= $be $b <= $cnon segue $a <= $c(Esempio uguale a ==).

  • Extra: l' <=operatore PHP non è totale , cioè entrambi $a <= $be $b <= $apuò essere falso:

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

Per costituire un ordine parziale rigoroso < / >deve essere irriflessivo, asimmetrico e transitivo:

  • L' <operatore di PHP non ha riflessi , cioè $a < $anon è mai vero. Nota che questo è vero solo a partire da PHP 5.4 . Precedentemente INF < INFvalutato a true.

  • L' <operatore di PHP non è asimmetrico , cioè da $a < $bnon segue !($b < $a)(Esempio identico a <=non essere antisimmetrico).

  • L' <operatore di PHP non è transitivo , cioè da $a < $be $b < $cnon segue $a < $c:

    var_dump(-INF < 0);    // bool(true)
    var_dump(0 < TRUE);    // bool(true)
    var_dump(-INF < TRUE); // bool(false)
  • Extra: l' <operatore di PHP non è tricotomo , cioè tutto $a < $b, $b < $ae $a == $bpuò essere falso (Esempio uguale a <=non essere totale).

  • Extra: l' <operatore di PHP può essere circolare , cioè è possibile che $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: l'esempio precedente genera un avviso "Impossibile convertire in double l'oggetto della classe stdClass".

Puoi trovare alcuni bei grafici per gli operatori di confronto di PHP su PHP Sadness 52 - Operatori di confronto .

Come ultima nota, voglio far notare che ci sono due uguaglianze che PHP fa garanzia (a differenza di praticamente tutto il resto). Questi due valgono sempre, semplicemente perché il compilatore riduce l'uno all'altro:

($a > $b) == ($b < $a)
($a >= $b) == ($b <= $a)

2
Wow, bella risposta. Quindi non è possibile formulare espressioni logiche con PHP come ($a > $b) and ($b > $c)con $a > $canche se la documentazione dice che quegli </ >operatori dicono che sono rigorosi ?
hakre

26
Gli operatori IMHO seguono le regole matematiche, ma solo quando hanno a che fare con gli stessi tipi di dati. Il casting di tipo è ciò che crea davvero la confusione qui (e in molte altre situazioni). Quando si confrontano numeri e stringhe e le conversioni di tipo di valori speciali vengono eseguite prima degli operatori, quindi gli operatori di confronto in senso stretto non
creano

6
@ ivanhoe011 La verità è: entrambi lo sono :) Le regole di confronto di PHP e le regole di casting di PHP differiscono , non puoi semplicemente dire che $a == $bè la stessa di (type) $a === (type) $b. Un semplice esempio di questo è che "15" == "0xf", ma (int) "15" !== (int) "0xf". E sia il confronto che le regole di casting in PHP sono totalmente folli ^^
NikiC

3
@NikiC: restituisce un (int)"0xf"numero intero 0, quindi ovviamente 0 !== 15. Il confronto in questo esempio si comporta esattamente come previsto. È il casting che crea confusione qui. Lo ammetto, (INF < INF) === trueera un vero problema di confronto, ma era un caso speciale ed è stato risolto come hai sottolineato. Ottima risposta .. +1
FtDRbwLXw6

1
Non necessariamente biasimo i progettisti di PHP per alcune delle decisioni che avevano senso sulla coercizione del tipo in quel momento ... ma sento che avrebbero dovuto notare i risultati di queste scelte di progettazione e rendersi immediatamente conto che le scelte erano ovviamente sbagliate. L'esempio più ovvio è il commento di @ ravz.
Ciad

88

Non ci sono non rigidi identici operatori di confronto ( >==o <==) in PHP (PHP 5.6.14 di almeno) , ma ci sono alcuni modi per far rispettare un rigoroso controllo di tipo prima di controllare maggiore / inferiore:

  1. Controlla entrambi i tipi di variabili con if (gettype($a) === gettype($b))
  2. Forza il cast di tipo necessario, ad es. if ((string)$a === (string)$b)
  3. Forza la giocoleria di tipo necessaria, ad es. if (($a . '') === ($b . ''))

Prendi nota che:

  • La precisione in virgola mobile è limitata
  • INFe NANsono di tipo floatsotto
  • Alcuni Infinity sono uguali ad altri Infinity (da PHP 5.4)
  • La notazione scientifica eè sempre di tipo floate mai integeranche se il numero è piccolo
  • I numeri interi che superano PHP_INT_MAXvengono convertiti automaticamente infloat
  • I galleggianti sui confini del sistema ottengono il INFvalore
  • Le variabili indefinite sono di tipo e valore NULL
  • I numeri interi preceduti da 0vengono convertiti da ottale a decimale (per convenzione)
  • La conversione di stringhe contenenti un intero con un interlinea 0 in un intero elimina l'interlinea0

Elenco di alcuni confronti esotici:

Molto strano:
     $ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b
  float (NAN) float (-INF) false false false false false false
  float (NAN) float (0) false false false false false false
  float (NAN) float (1) false false false false false false
  float (NAN) float (INF) false false false false false false
  float (NAN) float (NAN) false false false false false false
  float (NAN) int (-1) false false false false false false
  float (NAN) int (0) false false false false false false
  float (NAN) int (1) false false false false false false

Uguale ma non identico:

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

Più basso e più grande allo stesso tempo?

     $ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b
  float (NAN) str ("\ 0") true true true true false false
  float (NAN) str ('') true true true true false false
  float (NAN) str ('+') true true true true false false
  float (NAN) str ('-') true true true true false false
  float (NAN) str ('0') true true true true false false
  float (NAN) str ('01 ') true true true true false false
  float (NAN) str ('1') true true true true false false
  float (NAN) str ('false') true true true true false false
  float (NAN) str ('text') true true true true false false
  float (NAN) str ('true') true true true true false false

Uguale E identico:

     $ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b
  NULL (NULL) NULL (NULL) false false true true true true
 float (-INF) float (-INF) false false true true true true
  float (INF) float (INF) false false true true true true

Minore o Maggiore:

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

$a > $b > $cEnigma quando: $anon è maggiore di $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 (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 (true)> int (0)> int (-1)
A == C: bool (true)> int (0)> float (-1)
A == C: bool (true)> str ('0')> float (NAN)
A == C: bool (true)> str ('0')> float (-INF)
A == C: bool (true)> str ('0')> int (-1)
A == C: bool (true)> str ('0')> float (-1)
A == C: bool (true)> float (0)> float (-INF)
A == C: bool (true)> float (0)> int (-1)
A == C: bool (true)> float (0)> float (-1)
A == C: int (1)> str ('a')> str ('1')
LA == DO: int (1)> str ('LA')> 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 (false)
A == C: str ('')> int (-1)> NULL (NULL)
A == C: str ('')> int (-1)> bool (false)
A == C: str ('')> float (-1)> NULL (NULL)
A == C: str ('')> float (-1)> bool (false)
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 (false)
A == C: array ()> float (-INF)> NULL (NULL)
A == C: array ()> float (-INF)> bool (false)
A == C: array ()> str ('a')> NULL (NULL)
A == C: array ()> str ('a')> bool (false)
A == C: array ()> int (1)> NULL (NULL)
A == C: array ()> int (1)> bool (false)
A == C: array ()> float (1)> NULL (NULL)
A == C: array ()> float (1)> bool (false)
A == C: array ()> str ('1')> NULL (NULL)
A == C: array ()> str ('1')> bool (false)
A == C: array ()> str ('A')> NULL (NULL)
A == C: array ()> str ('A')> bool (false)
A == C: array ()> str ('0')> NULL (NULL)
A == C: array ()> int (-1)> NULL (NULL)
A == C: array ()> int (-1)> bool (false)
A == C: array ()> float (-1)> NULL (NULL)
A == C: array ()> float (-1)> bool (false)
A == C: str ('')> float (NAN)> bool (false)
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 (false)
A == C: int (0)> int (-1)> NULL (NULL)
A == C: int (0)> int (-1)> bool (false)
A == C: int (0)> float (-1)> NULL (NULL)
A == C: int (0)> float (-1)> bool (false)
A == C: str ('0')> float (NAN)> bool (false)
A == C: str ('0')> float (-INF)> bool (false)
A == C: str ('0')> int (-1)> bool (false)
A == C: str ('0')> float (-1)> bool (false)
A == C: float (0)> float (-INF)> NULL (NULL)
A == C: float (0)> float (-INF)> bool (false)
A == C: float (0)> int (-1)> NULL (NULL)
A == C: float (0)> int (-1)> bool (false)
A == C: float (0)> float (-1)> NULL (NULL)
A == C: float (0)> float (-1)> bool (false)
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')

Divertente confronto delle stringhe: 'Regina' >'Re' >'Jack' >'Asso'

Controlla anche le tabelle di confronto dei tipi PHP che coprono le coppie:

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

Controlla le differenze tra le versioni PHP in diretta su. http://3v4l.org/MAfDu .


26
+1 per non parlare delle "tabelle" scorrevoli con le intestazioni di colonne fisse - idea ingegnosa;)
hakre

È necessario utilizzare l'operatore rigoroso durante il casting del tipo? Voglio dire che hai scritto if ( (string)$a===(string)$b )ma non è esattamente lo stesso di if ( (string)$a==(string)$b )?
Voitcus

@Voitcus yes sia per type-cast (string)1==(string)'01'-> bool(true)che per type-juggle (1 . '')=='01'-> bool(true)non esattamente lo stesso di ===quando avrestibool(false) su entrambi gli account
CSᵠ

1
Un problema: i valori ottali non vengono "convertiti su assegnazione", sono interpretati dal compilatore, che deve trasformare ASCII in numeri binari effettivi.
IMSoP

INFINITY is equal to INFINITY which is mathematically incorrect!è un'affermazione decisamente discutibile. Si noti inoltre che NaNper convenzione non è maggiore, minore o uguale a qualsiasi cosa in qualsiasi linguaggio di programmazione che io conosca.
DaveRandom

22

Dopo aver corretto la seconda parte della tua domanda, lascio la risposta a quella parte alle altre. Voglio solo dare la risposta più sorprendente alla prima parte della tua domanda, cioè se c'è un esempio di operatori <e >intransitivi. Ecco qui.

Questi sono tutti true:

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

Se <fosse transitivo ( $a < $b$b < $c$a < $c), l'ultima riga sarebbe

"10" < "2"

ma PHP cerca di essere gentile (?!) e interpreta le stringhe come numeri ogni volta che può.

Si scopre che, a causa della suddetta intransitività, è sort()possibile ordinare gli stessi elementi in un ordine diverso a seconda del loro ordine di input, anche quando non ci sono due elementi== (e nessun elemento è NAN). L'ho sottolineato in un commento a sort () , la cui essenza è:

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" )

1
il commento precedente fa riferimento ad una parte della risposta (relativa alla seconda parte della domanda) che ho nel frattempo cancellato
Walter Tross

Rimosso quello ora;) E una bella nuova sort()tabella, scelta anche per le implicazioni pratiche durante la scrittura del relativo post sul blog The Greatest PHP Value . Grazie ancora per la tua risposta.
hakre

Significa che si dovrebbe usare usortquando possibile?
Voitcus

2
@ Voitcus: immagino tu intenda usort($arr, 'strcmp'). Funziona (per le stringhe, ovviamente), ma è meglio usarlo sort($arr, SORT_STRING).
Walter Tross

@WalterTross Voglio dire, usa sempre la tua funzione (non solo per gli archi) per assicurarti che sia sempre corretta
Voitcus
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.