Żonglowanie typami i (ścisłe) porównania większe / mniejsze niż w PHP

115

PHP słynie z żonglowania typami. Muszę przyznać, że intryguje mnie to i ciężko mi jest znaleźć podstawowe logiczne / fundamentalne rzeczy w porównaniach.

Na przykład: Jeśli $a > $bjest prawdą i $b > $cjest prawdą, czy musi to oznaczać, że zawsze$a > $c jest prawdą?

Kierując się podstawową logiką, powiedziałbym tak, ale jestem zdziwiony, że nie ufam w tym PHP. Może ktoś może podać przykład, gdzie tak nie jest?

Zastanawiam się również z operatorami ściśle mniejszymi niż i ścisłymi większymi niż (ponieważ ich znaczenie jest opisane jako ścisłe, które znałem tylko w przeszłości z porównań równości), czy ma znaczenie, czy lewy i prawy operand są zamienione z wartości ściśle nierówne:

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

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

W przypadku większości kombinacji porównania typów te większe / mniejsze operatory porównania nie są udokumentowane, więc przeczytanie instrukcji nie było w tym przypadku zbyt pomocne.

hakre
źródło
Myślę, że chcesz poprawić tę linię ($a > $b) !== ($b < $a)?
Walter Tross,
ah, ok, więc źle to zrozumiałem. Będę musiał odpowiednio poprawić moją odpowiedź. Zabawne, że wszyscy ci ludzie piszą traktaty zamiast odpowiedzi i nie czytają uważnie twojego pytania ...
Walter Tross

Odpowiedzi:

208

Operatory porównania PHP odbiegają od definicji komputerowo-naukowych na kilka sposobów:

Aby relacja równoważności == mogła być utworzona, musi być zwrotna, symetryczna i przechodnia:

  • ==Operator PHP nie jest zwrotny , tj. $a == $aNie zawsze jest prawdziwy:

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

    Uwaga: Fakt, że każde porównanie NANjest zawsze falsezwiązane z PHP. Jest to wymagane przez standard IEEE 754 dla arytmetyki zmiennoprzecinkowej ( więcej informacji ).

  • ==Operator PHP jest symetryczny , tj. $a == $bI $b == $azawsze jest taki sam.

  • PHP ==operator jest nie przechodni , czyli od $a == $bi $b == $cma nie następująco $a == $c:

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

Aby stanowić porządek częściowy <= / >=musi być zwrotny, antysymetryczny i przechodni:

  • <=Operator PHP nie jest zwrotny , tj. $a <= $aNie zawsze jest prawdziwy (przykład taki sam jak for ==).

  • <=Operator PHP nie jest anty-symetryczny , tj. Z $a <= $bi $b <= $anie wynika $a == $b:

    var_dump(NAN <= "foo"); // bool(true)
    var_dump("foo" <= NAN); // bool(true)
    var_dump(NAN == "foo"); // bool(false)
    
  • <=Operator PHP nie jest przechodni , tj. Od $a <= $bi $b <= $cnie następuje $a <= $c(przykład taki sam jak for ==).

  • Dodatkowo: <=operator PHP nie jest całkowity , tj. Oba $a <= $bi $b <= $amogą być fałszywe:

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

Aby stanowić ścisły porządek cząstkowy < / >musi być nieodwracalny, asymetryczny i przechodni:

  • <Operator PHP jest nierefleksyjny , tj. $a < $aNigdy nie jest prawdziwy. Zauważ, że jest to prawdą tylko od PHP 5.4 . Wcześniej INF < INFoceniane do true.

  • <Operator PHP nie jest asymetryczny , tj. $a < $bFrom nie następuje !($b < $a)(przykład taki sam jak w przypadku <=braku anty-symetrii).

  • <Operator PHP nie jest przechodni , tj. Od $a < $bi $b < $cnie następuje $a < $c:

    var_dump(-INF < 0);    // bool(true)
    var_dump(0 < TRUE);    // bool(true)
    var_dump(-INF < TRUE); // bool(false)
    
  • Dodatkowo: <operator PHP nie jest trychotomiczny , tj. All of $a < $b, $b < $ai $a == $bmoże być fałszywy (przykład taki sam, jak w przypadku <=braku sumy).

  • Extra: PHP <operator może być okrągły , to znaczy, że jest to możliwe $a < $b, $b < $ci $c < $a:

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

    Uwaga: Powyższy przykład generuje powiadomienie „Nie można przekonwertować obiektu klasy stdClass na podwójny”.

Możesz znaleźć kilka ładnych wykresów dla operatorów porównania PHP na stronie PHP Sadness 52 - Operatory porównania .

Jako ostatnią nutę, chcę podkreślić, że istnieją dwie równości że PHP ma gwarancji (w przeciwieństwie do niemal wszystkiego innego). Te dwa zawsze się trzymają, po prostu dlatego, że kompilator redukuje jedno do drugiego:

($a > $b) == ($b < $a)
($a >= $b) == ($b <= $a)
NikiC
źródło
2
Wow, miła odpowiedź. Więc nie jest możliwe sformułowanie logicznych wyrażeń w PHP, tak jak w ($a > $b) and ($b > $c)przypadku, $a > $cmimo że dokumentacja mówi, że operatorzy </ >mówią, że są ścisłe ?
hakre
26
Operatorzy IMHO przestrzegają reguł matematycznych, ale tylko wtedy, gdy mają do czynienia z tymi samymi typami danych. Rzutowanie typów jest tym, co naprawdę powoduje zamieszanie tutaj (i w wielu innych sytuacjach). Przy porównywaniu liczb i ciągów i specjalne konwersji wartości typu są wykonywane przed operatorami, tak ściśle mówiąc operatory porównania nie są mylące, odlew jest ...
Ivanhoe
6
@ ivanhoe011 Prawda jest taka: Oba są :) Reguły porównawcze PHP i rzutowania różnią się , nie można po prostu powiedzieć, że $a == $bto to samo co (type) $a === (type) $b. Prostym tego przykładem jest to "15" == "0xf", ale (int) "15" !== (int) "0xf". I zarówno porównanie, jak i reguły castingu w PHP są totalnie szalone ^^
NikiC,
3
@NikiC: (int)"0xf"ewaluuje do liczby całkowitej 0, więc oczywiście 0 !== 15. Porównanie w tym przykładzie zachowuje się dokładnie tak, jak oczekiwano. To casting jest mylący. Przyznaję, (INF < INF) === truebył to prawdziwy problem z porównaniem, ale był to szczególny przypadek i został rozwiązany, jak wskazałeś. Świetna odpowiedź… +1
FtDRbwLXw6
1
Niekoniecznie muszę winić projektantów PHP za niektóre z decyzji, które miały wtedy sens w kwestii wymuszania typów ... ale czuję, że powinni byli zauważyć wyniki tych wyborów projektowych i natychmiast zdać sobie sprawę, że wybory były oczywiście błędne. Najbardziej oczywistym przykładem jest komentarz @ ravz.
Czad
88

W PHP nie ma ściśle identycznych operatorów porównania ( >==lub <==) (przynajmniej od PHP 5.6.14) , ale istnieje kilka sposobów na wymuszenie ścisłego sprawdzenia typu przed sprawdzeniem Większy / Dolny:

  1. Zaznacz oba typy zmiennych za pomocą if (gettype($a) === gettype($b))
  2. Wymuś potrzebny typ rzutowania, np. if ((string)$a === (string)$b)
  3. Wymuś żonglowanie typami, np. if (($a . '') === ($b . ''))

Zwróć uwagę, że:

  • Precyzja zmiennoprzecinkowa jest ograniczona
  • INFi NANsą typu floatunder
  • Pewna nieskończoność równa się innej Infinity (od PHP 5.4)
  • Notacja naukowa ejest zawsze typu floati nigdy, integernawet jeśli liczba jest mała
  • Przechodzące liczby całkowite PHP_INT_MAXsą automatycznie konwertowane nafloat
  • Przepływa przez granice systemu, uzyskując INFwartość
  • Niezdefiniowane zmienne są typu i wartości NULL
  • Liczby całkowite poprzedzone przez 0są konwertowane z ósemkowego na dziesiętny (zgodnie z konwencją)
  • Konwersja ciągów zawierających liczbę całkowitą z początkiem 0 na liczbę całkowitą usuwa początkowe0

Lista egzotycznych porównań:

Bardzo dziwny:
     $ 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 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

Równe, ale nie identyczne:

     $ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b
  NULL (NULL) array () false false true true true true false
  NULL (NULL) bool (false) false false true true true true false
  NULL (NULL) float (0) false false true true true true false
  NULL (NULL) int (0) false false true true true true false
  NULL (NULL) str ('') false false true true true false
   array () bool (false) false false true true true true false
 bool (false) float (0) false false true true true true false
 bool (false) int (0) false false true true true true false
   str ('') bool (false) false false true true true true false
 bool (false) str ('0') false false true true true true false
 float (-INF) bool (prawda) fałsz fałsz prawda prawda prawda prawda fałsz
  bool (true) float (1) false false true true true true false
  float (INF) bool (true) false false true true true true false
  float (NAN) bool (true) false false true true true true false
  bool (true) int (-1) false false true true true true true false
  bool (true) int (1) false false true true true true true false
  bool (true) str ("\ 0") false false true true true true false
  bool (true) str ('+') false false true true true true false
  bool (true) str ('-') false false true true true true false
  bool (true) str ('01 ') false false true true true true false
  bool (true) str ('1') false false true true true true false
  bool (true) str ('false') false false true true true true false
 str ('text') bool (true) false false true true true true false
 str ('true') bool (true) false false true true true true false
    int (0) float (0) false false true true true true false
  str ("\ 0") float (0) false false true true true true false
   str ('') float (0) false false true true true true false
   str ('+') float (0) false false true true true true false
   str ('-') float (0) false false true true true true false
   str ('0') float (0) false false true true true true false
 str ('false') float (0) false false true true true true true false
 str ('text') float (0) false false true true true true false
 str ('prawda') float (0) fałsz fałsz prawda prawda prawda prawda fałsz
    int (1) float (1) false false true true true true false
   float (1) str ('01 ') false false true true true true false
   float (1) str ('1') false false true true true true false
  str ("\ 0") int (0) false false true true true true false
   str ('') int (0) false false true true true true false
   str ('+') int (0) false false true true true true false
   str ('-') int (0) false false true true true true false
    int (0) str ('0') false false true true true true false
 str ('false') int (0) false false true true true true false
 str ('tekst') int (0) false false true true true true false
 str ('prawda') int (0) fałsz fałsz prawda prawda prawda prawda fałsz
    int (1) str ('01 ') false false true true true true false
    int (1) str ('1') false false true true true true false
   str ('1') str ('01 ') false false true true true true false

Niższy i większy w tym samym czasie?

     $ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b
  float (NAN) str ("\ 0") prawda prawda prawda prawda fałsz fałsz
  float (NAN) str ('') prawda prawda prawda prawda fałsz fałsz
  float (NAN) str ('+') prawda prawda prawda prawda fałsz fałsz
  float (NAN) str ('-') prawda prawda prawda prawda fałsz fałsz
  float (NAN) str ('0') prawda prawda prawda prawda fałsz fałsz
  float (NAN) str ('01 ') prawda prawda prawda prawda fałsz fałsz
  float (NAN) str ('1') prawda prawda prawda prawda fałsz fałsz
  float (NAN) str ('false') true true true true true false false
  float (NAN) str ('tekst') prawda prawda prawda prawda fałsz fałsz
  float (NAN) str ('true') true true prawda prawda prawda fałsz fałsz

Równe I identyczne:

     $ 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) fałsz fałsz prawda prawda prawda prawda prawda
  float (INF) float (INF) false false true true true true true

Mniejsze lub większe:

     $ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b
  NULL (NULL) bool (true) false true true true false false false
 float (-INF) NULL (NULL) prawda fałsz fałsz prawda fałsz fałsz
  NULL (NULL) float (1) false true true false false false
  float (INF) NULL (NULL) prawda fałsz fałsz prawda fałsz fałsz
  float (NAN) NULL (NULL) prawda fałsz fałsz prawda fałsz fałsz
  NULL (NULL) int (-1) false true true false false false
  NULL (NULL) int (1) false true true false false false
  NULL (NULL) str ("\ 0") false true true false false false
  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') false true true false false false
  NULL (NULL) str ('false') false true true true false false false
  NULL (NULL) str ('tekst') false true true false false false
  NULL (NULL) str ('true') false true true true false false false
   array () bool (true) false true true false false false false
 float (-INF) array () false true true true false false false
   array () float (0) prawda fałsz fałsz prawda fałsz fałsz
   array () float (1) prawda fałsz fałsz prawda fałsz fałsz
  float (INF) array () false true true true false false false
  float (NAN) array () false true true false false false false
   array () int (-1) prawda fałsz fałsz prawda fałsz fałsz
   array () int (0) prawda fałsz fałsz prawda fałsz fałsz
   array () int (1) prawda fałsz fałsz prawda fałsz fałsz
   array () str ("\ 0") prawda fałsz fałsz prawda fałsz fałsz
   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') prawda fałsz fałsz prawda fałsz fałsz
   array () str ('01 ') true false false true true false false
   array () str ('1') true false false true false false
   array () str ('false') true false false true true false false
   array () str ('tekst') prawda fałsz fałsz prawda fałsz fałsz
   array () str ('true') true false false true false false
  bool (prawda) bool (fałsz) prawda fałsz fałsz prawda fałsz fałsz fałsz
 float (-INF) bool (false) true false false true 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 true false false
 bool (false) int (-1) false true true false false false false
    int (1) bool (false) true false false true false false
 bool (false) str ("\ 0") false true true false false false
 bool (false) str ('+') false true true false false false false
 bool (false) str ('-') false true true false false false false
 bool (false) str ('01 ') false true true false false false false
   str ('1') bool (false) true false false true true false false
 bool (false) str ('false') false true true false false false false
 str ('text') bool (false) true false false true true false false
 str ('true') bool (false) true false false true true false false
  bool (prawda) float (0) prawda fałsz fałsz prawda fałsz fałsz
  bool (prawda) int (0) prawda fałsz fałsz prawda fałsz fałsz
   str (``) bool (true) false true true true false false false
  bool (true) str ('0') true false false true false false
 float (-INF) float (0) fałsz prawda prawda fałsz fałsz fałsz
 float (-INF) float (1) fałsz prawda prawda fałsz fałsz fałsz
  float (INF) float (-INF) prawda fałsz fałsz prawda fałsz fałsz
 float (-INF) int (-1) false true true false false false false
 float (-INF) int (0) false true true false false false false
 float (-INF) int (1) false true true false false false false
 float (-INF) str ("\ 0") false true true false false false
 float (-INF) str ('') false true true false 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 true false false false
 float (-INF) str ('tekst') false true true false false false
 float (-INF) str ('true') false true true true false false false
   float (1) float (0) prawda fałsz fałsz prawda fałsz fałsz
  float (INF) float (0) prawda fałsz fałsz prawda fałsz fałsz
   float (0) int (-1) prawda fałsz fałsz prawda fałsz fałsz
    int (1) float (0) prawda fałsz fałsz prawda fałsz fałsz
   float (0) str ('01 ') false true true false false false false
   str ('1') float (0) prawda fałsz fałsz prawda fałsz fałsz
  float (INF) float (1) prawda fałsz fałsz prawda fałsz fałsz
   float (1) int (-1) prawda fałsz fałsz prawda fałsz fałsz
   float (1) int (0) prawda fałsz fałsz prawda fałsz fałsz
   float (1) str ("\ 0") prawda fałsz fałsz prawda fałsz fałsz
   str ('') float (1) false true true false false false
   float (1) str ('+') true false false true false false
   float (1) str ('-') prawda fałsz fałsz prawda fałsz fałsz
   float (1) str ('0') prawda fałsz fałsz prawda fałsz fałsz
   float (1) str ('false') true false false true false false
 str ('tekst') float (1) false true true false false false
 str ('true') float (1) false true true false false false false
  float (INF) int (-1) prawda fałsz fałsz prawda fałsz fałsz
  float (INF) int (0) prawda fałsz fałsz prawda fałsz fałsz
  float (INF) int (1) prawda fałsz fałsz prawda fałsz fałsz
  float (INF) str ("\ 0") prawda fałsz fałsz prawda fałsz fałsz
  float (INF) str ('') prawda fałsz fałsz prawda fałsz fałsz
  float (INF) str ('+') prawda fałsz fałsz prawda fałsz fałsz
  float (INF) str ('-') prawda fałsz fałsz prawda fałsz fałsz
  float (INF) str ('0') prawda fałsz fałsz prawda fałsz fałsz
  float (INF) str ('01 ') prawda fałsz fałsz prawda fałsz fałsz
  float (INF) str ('1') prawda fałsz fałsz prawda fałsz fałsz
  float (INF) str ('false') true false false true false false
  float (INF) str ('tekst') prawda fałsz fałsz prawda fałsz fałsz
  float (INF) str ('true') true false false true false false
    int (0) int (-1) prawda fałsz fałsz prawda fałsz fałsz
    int (1) int (-1) prawda fałsz fałsz prawda fałsz fałsz
  str ("\ 0") int (-1) prawda fałsz fałsz prawda fałsz fałsz
   str ('') int (-1) prawda fałsz fałsz prawda fałsz fałsz
   str ('+') int (-1) prawda fałsz fałsz prawda fałsz fałsz
   str ('-') int (-1) prawda fałsz fałsz prawda fałsz fałsz
   str ('0') int (-1) prawda fałsz fałsz prawda fałsz fałsz
   int (-1) str ('01 ') false true true false false false false
   str ('1') int (-1) prawda fałsz fałsz prawda fałsz fałsz
 str ('false') int (-1) true false false true true false false
 str ('tekst') int (-1) prawda fałsz fałsz prawda fałsz fałsz
 str ('prawda') int (-1) prawda fałsz fałsz prawda fałsz fałsz
    int (1) int (0) prawda fałsz fałsz prawda fałsz fałsz
    int (0) str ('01 ') false true true false false false false
   str ('1') int (0) prawda fałsz fałsz prawda fałsz fałsz
    int (1) str ("\ 0") prawda fałsz fałsz prawda fałsz fałsz
   str ('') int (1) false true true false false false false
    int (1) str ('+') true false false true false false
    int (1) str ('-') true false false true false false
    int (1) str ('0') prawda fałsz fałsz prawda fałsz fałsz
    int (1) str ('false') true false false true false false
 str ('tekst') int (1) false true true false false false
 str ('true') int (1) false true true false false false false
   str ('') str ("\ 0") false true true false false false
   str ('+') str ("\ 0") prawda fałsz fałsz prawda fałsz fałsz
   str ('-') str ("\ 0") prawda fałsz fałsz prawda fałsz fałsz
  str ("\ 0") str ('0') false true true false false false
  str ("\ 0") str ('01 ') false true true false false false
   str ('1') str ("\ 0") prawda fałsz fałsz prawda fałsz fałsz
 str ('false') str ("\ 0") true false false true false false
 str ('tekst') str ("\ 0") prawda fałsz fałsz prawda fałsz fałsz
 str ('prawda') str ("\ 0") prawda fałsz fałsz prawda fałsz fałsz
   str ('') str ('+') false true true false false false
   str ('') str ('-') false true true false false false
   str ('') str ('0') false true true false false false false
   str ('') str ('01 ') false true true false false false false
   str ('') str ('1') false true true false false false false
   str ('') str ('false') false true true false false false false
   str ('') str ('tekst') false true true false false false
   str ('') str ('true') false true true false false false false
   str ('-') str ('+') prawda fałsz fałsz prawda fałsz fałsz
   str ('+') str ('0') false true true false false false
   str ('+') str ('01 ') false true true false false false
   str ('1') str ('+') prawda fałsz fałsz prawda fałsz fałsz
 str ('false') str ('+') true false false true false false
 str ('tekst') str ('+') prawda fałsz fałsz prawda fałsz fałsz
 str ('true') str ('+') true false false true false false
   str ('-') str ('0') false true true false false false
   str ('-') str ('01 ') false true true false false false
   str ('1') str ('-') prawda fałsz fałsz prawda fałsz fałsz
 str ('false') str ('-') true false false true false false
 str ('tekst') str ('-') prawda fałsz fałsz prawda fałsz fałsz
 str ('prawda') str ('-') prawda fałsz fałsz prawda fałsz fałsz
   str ('0') str ('01 ') false true true false false false
   str ('1') str ('0') prawda fałsz fałsz prawda fałsz fałsz
 str ('false') str ('0') true false false true false false
 str ('tekst') str ('0') prawda fałsz fałsz prawda fałsz fałsz
 str ('prawda') str ('0') prawda fałsz fałsz prawda fałsz fałsz
 str ('false') str ('01 ') true false false true false false
 str ('text') str ('01 ') true false false true false false
 str ('prawda') str ('01 ') prawda fałsz fałsz prawda fałsz fałsz fałsz
   str ('1') str ('false') false true true true false false false
 str ('tekst') str ('1') prawda fałsz fałsz prawda fałsz fałsz
 str ('prawda') str ('1') prawda fałsz fałsz prawda fałsz fałsz
 str ('text') str ('false') true false false true false false
 str ('prawda') str ('fałsz') prawda fałsz fałsz prawda fałsz fałsz
 str ('prawda') str ('tekst') prawda fałsz fałsz prawda fałsz fałsz

$a > $b > $cZagadka, gdy: $anie jest większe niż $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')
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 (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')

Zabawne porównanie strun: „Dama” >„Król” >„Walet” >„As”

Sprawdź również tabele porównawcze typów PHP obejmujące pary:

  • isset() i is_null()
  • if() i empty()
  • boolean ==vs.===

Sprawdź różnice między wersjami PHP dostępnymi pod adresem. http://3v4l.org/MAfDu .

CSᵠ
źródło
26
+1 nie mówiąc już o przewijanych „tabelach” ze stałymi nagłówkami kolumn
niezły
Czy przy rzutowaniu typów trzeba używać operatora ścisłego? To znaczy napisałeś, if ( (string)$a===(string)$b )ale czy to nie jest dokładnie to samo co if ( (string)$a==(string)$b )?
Voitcus,
@Voitcus tak dla obu typów (string)1==(string)'01'-> bool(true)i dla typu juggle (1 . '')=='01'-> bool(true)nie dokładnie to samo, co w ===przypadku bool(false)obu kont
CSᵠ
1
Jeden wybór: wartości ósemkowe nie są „konwertowane przy przypisaniu”, są one interpretowane przez kompilator, który musi przekształcić ASCII w rzeczywiste liczby binarne.
IMSoP
INFINITY is equal to INFINITY which is mathematically incorrect!jest zdecydowanie dyskusyjnym stwierdzeniem. Zauważ również, że NaNzgodnie z konwencją jest to nie większe niż, mniejsze lub równe czegokolwiek w jakimkolwiek znanym mi języku programowania.
DaveRandom,
22

Po poprawieniu drugiej części pytania, odpowiedź na tę część pozostawiam pozostałym. Chcę tylko udzielić najbardziej zaskakującej odpowiedzi na pierwszą część twojego pytania, tj. Czy istnieje przykład nieprzechodni operatorów <i >. Tutaj jest.

To wszystko true:

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

Gdyby <była przechodnia ( $a < $b$b < $c$a < $c), ostatnia linia byłaby

"10" < "2"

ale PHP stara się być uprzejmy (?!) i interpretować łańcuchy jako liczby, kiedy tylko może.

Okazuje się, że ze względu na powyższą nieprzechodność, sort()może sortować te same elementy w różnej kolejności w zależności od ich kolejności wejściowej, nawet gdy nie ma dwóch elementów== (i żaden element nie jest NAN). Zwróciłem na to uwagę w komentarzu do sort () , którego istotą jest:

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
źródło
1
poprzedni komentarz odnosi się do części odpowiedzi (odnoszącej się do drugiej części pytania), którą w międzyczasie skasowałem
Walter Tross 08.04.13
Usunąłem to teraz;) I ładny nowy sort()stół, wybrałem go również ze względu na praktyczne implikacje podczas pisania powiązanego wpisu na blogu The Greatest PHP Value . Jeszcze raz dziękuję za odpowiedź.
hakre
Czy to oznacza, że ​​należy używać, usortgdy tylko jest to możliwe?
Voitcus
2
@Voitcus: Chyba masz na myśli usort($arr, 'strcmp'). To działa (oczywiście w przypadku stringów), ale najlepiej jest używać sort($arr, SORT_STRING).
Walter Tross,
@WalterTross Mam na myśli, że zawsze używaj własnej funkcji (nie tylko dla smyczków), aby upewnić się, że jest zawsze poprawna
Voitcus