Тип-жонглирование и (строгое) большее/меньшее, чем сравнение в PHP

PHP известен своим жужжанием типа. Я должен признать, что это меня озадачивает, и мне сложно найти основные логические/фундаментальные вещи в сравнении.

Например: Если $a > $b истинно, а $b > $c - true, значит, оно означает, что $a > $c тоже всегда верно?

Следуя основной логике, я бы сказал, что да, но я озадачен тем, что в действительности я не доверяю PHP. Может быть, кто-то может предоставить пример, где это не так?

Также мне интересно со строгими меньшими и строгими операторами большего размера (поскольку их значение описывается как строгое, о котором я знал только в прошлом из сравнений равенства), если это имеет значение, если левый и правый операнды заменяются строго неравными значениями:

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

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

Для большинства комбинаций сравнения типов эти большие/меньшие операторы сравнения не документируются, поэтому чтение руководства в этом случае не очень полезно.

Ответ 1

Операторы сравнения PHP отклоняются от компьютерно-научных определений несколькими способами:

Чтобы составить отношение эквивалентности == должно быть рефлексивным, симметричным и транзитивным:

  • Оператор PHP == не рефлексивный, т.е. $a == $a не всегда верно:

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

    Примечание. Тот факт, что любое сравнение с NAN всегда false не является специфичным для PHP. Это предусмотрено стандартом IEEE 754 для арифметики с плавающей точкой (подробнее).

  • Оператор PHP == симметричный, т.е. $a == $b и $b == $a всегда одни и те же.

  • Оператор PHP == не транзитивен, т.е. от $a == $b и $b == $c следует не $a == $c:

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

Чтобы составить частичный порядок <=/>=, должен быть рефлексивным, антисимметричным и транзитивным:

  • Оператор PHP <= не рефлексивный, т.е. $a <= $a не всегда верен (пример такой же, как для ==).

  • Оператор PHP <= не является антисимметричным, т.е. из $a <= $b и $b <= $a не следует $a == $b:

    var_dump(NAN <= "foo"); // bool(true)
    var_dump("foo" <= NAN); // bool(true)
    var_dump(NAN == "foo"); // bool(false)
    
  • Оператор PHP <= не транзитивен, т.е. из $a <= $b и $b <= $c не следует $a <= $c (пример такой же, как для ==).

  • Дополнительно: PHP <= оператор не полный, то есть оба $a <= $b и $b <= $a могут быть ложными:

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

Для того чтобы составить строгий частичный порядок </> должен быть нерефлексивным, асимметричным и транзитивным:

  • Оператор PHP < нерефлексивный, т.е. $a < $a никогда не будет истинным. Обратите внимание, что это правда только с PHP 5.4. Ранее INF < INF оценивалось до true.

  • Оператор PHP < не асимметричен, т.е. из $a < $b не следует !($b < $a) (пример такой же, как для <= не является антисимметричным).

  • Оператор PHP < не транзитивен, т.е. из $a < $b и $b < $c не следует $a < $c:

    var_dump(-INF < 0);    // bool(true)
    var_dump(0 < TRUE);    // bool(true)
    var_dump(-INF < TRUE); // bool(false)
    
  • Дополнительно: PHP < оператор не трихотомический, т.е. все $a < $b, $b < $a и $a == $b могут быть ложными (пример такой же, как для <= not будучи полным).

  • Дополнительно: оператор PHP < может быть круговой, то есть возможно, что $a < $b, $b < $c и $c < $a:

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

    Примечание. В приведенном выше примере выдается сообщение об ошибке "Объект класса stdClass не может быть преобразован в двойное".

Вы можете найти несколько хороших графиков для операторов сравнения PHP на PHP Sadness 52 - Операторы сравнения.

Как последнее примечание, я хочу отметить, что есть два равенства, которые гарантирует PHP (в отличие от почти всего остального). Эти два всегда выполняются просто потому, что компилятор сводит один к другому:

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

Ответ 2

Существуют строгие идентичные операторы сравнения нет (>== или <==) в PHP (по крайней мере, по PHP 5.6.14), но есть несколько способов обеспечить соблюдение строгая проверка типа перед проверкой "Большой/Нижний":

  • Проверьте оба типа переменных с помощью if (gettype($a) === gettype($b))
  • Принудительно введите тип, например. if ((string)$a === (string)$b)
  • Принудительный тип жонглирования, например. if (($a . '') === ($b . ''))

Обратите внимание, что:

  • Точность плавающей точки ограничена
  • INF и NAN имеют тип float под
  • Некоторая бесконечность равна некоторой другой бесконечности (начиная с PHP 5.4)
  • Научная нотация e всегда имеет тип float и никогда integer, даже если число мало
  • Целые числа, переходящие PHP_INT_MAX, автоматически преобразуются в float
  • Поплавки по границам системы получают значение INF
  • Undefined переменные имеют тип и значение NULL
  • Целые числа, предшествующие 0, преобразуются из восьмеричного в десятичное (по соглашению)
  • Преобразование строк, содержащих целое число с ведущим 0 в integer, разделяет ведущий 0

Список некоторых экзотических сравнений:

Very strange:
     $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

Равно, но не идентично:

     $a      VS.     $b         $a>$b   $a<$b   $a<=$b  $a>=$b  $a==$b  $a===$b
  NULL(NULL)      array()       false   false    true    true    true   false
  NULL(NULL)    bool(false)     false   false    true    true    true   false
  NULL(NULL)      float(0)      false   false    true    true    true   false
  NULL(NULL)       int(0)       false   false    true    true    true   false
  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)       false   false    true    true    true   false
   str('')         int(0)       false   false    true    true    true   false
   str('+')        int(0)       false   false    true    true    true   false
   str('-')        int(0)       false   false    true    true    true   false
    int(0)        str('0')      false   false    true    true    true   false
 str('false')      int(0)       false   false    true    true    true   false
 str('text')       int(0)       false   false    true    true    true   false
 str('true')       int(0)       false   false    true    true    true   false
    int(1)       str('01')      false   false    true    true    true   false
    int(1)        str('1')      false   false    true    true    true   false
   str('1')      str('01')      false   false    true    true    true   false

Вниз и больше в одно и то же время?

     $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

Равно и тождественно:

     $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

Нижнее или большее:

     $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)      true   false   false    true   false   false
  NULL(NULL)      float(1)      false    true    true   false   false   false
  float(INF)     NULL(NULL)      true   false   false    true   false   false
  float(NAN)     NULL(NULL)      true   false   false    true   false   false
  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   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)       true   false   false    true   false   false
   array()        float(1)       true   false   false    true   false   false
  float(INF)      array()       false    true    true   false   false   false
  float(NAN)      array()       false    true    true   false   false   false
   array()        int(-1)        true   false   false    true   false   false
   array()         int(0)        true   false   false    true   false   false
   array()         int(1)        true   false   false    true   false   false
   array()       str("\0")       true   false   false    true   false   false
   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')       true   false   false    true   false   false
   array()       str('01')       true   false   false    true   false   false
   array()        str('1')       true   false   false    true   false   false
   array()      str('false')     true   false   false    true   false   false
   array()      str('text')      true   false   false    true   false   false
   array()      str('true')      true   false   false    true   false   false
  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)       false    true    true   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
 bool(false)      str('-')      false    true    true   false   false   false
 bool(false)     str('01')      false    true    true   false   false   false
   str('1')     bool(false)      true   false   false    true   false   false
 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)        true   false   false    true   false   false
    int(1)        float(0)       true   false   false    true   false   false
   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)        true   false   false    true   false   false
   float(1)        int(0)        true   false   false    true   false   false
   float(1)      str("\0")       true   false   false    true   false   false
   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)        true   false   false    true   false   false
  float(INF)       int(0)        true   false   false    true   false   false
  float(INF)       int(1)        true   false   false    true   false   false
  float(INF)     str("\0")       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('-')       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)        true   false   false    true   false   false
    int(1)        int(-1)        true   false   false    true   false   false
  str("\0")       int(-1)        true   false   false    true   false   false
   str('')        int(-1)        true   false   false    true   false   false
   str('+')       int(-1)        true   false   false    true   false   false
   str('-')       int(-1)        true   false   false    true   false   false
   str('0')       int(-1)        true   false   false    true   false   false
   int(-1)       str('01')      false    true    true   false   false   false
   str('1')       int(-1)        true   false   false    true   false   false
 str('false')     int(-1)        true   false   false    true   false   false
 str('text')      int(-1)        true   false   false    true   false   false
 str('true')      int(-1)        true   false   false    true   false   false
    int(1)         int(0)        true   false   false    true   false   false
    int(0)       str('01')      false    true    true   false   false   false
   str('1')        int(0)        true   false   false    true   false   false
    int(1)       str("\0")       true   false   false    true   false   false
   str('')         int(1)       false    true    true   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')       true   false   false    true   false   false
    int(1)      str('false')     true   false   false    true   false   false
 str('text')       int(1)       false    true    true   false   false   false
 str('true')       int(1)       false    true    true   false   false   false
   str('')       str("\0")      false    true    true   false   false   false
   str('+')      str("\0")       true   false   false    true   false   false
   str('-')      str("\0")       true   false   false    true   false   false
  str("\0")       str('0')      false    true    true   false   false   false
  str("\0")      str('01')      false    true    true   false   false   false
   str('1')      str("\0")       true   false   false    true   false   false
 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('')        str('+')      false    true    true   false   false   false
   str('')        str('-')      false    true    true   false   false   false
   str('')        str('0')      false    true    true   false   false   false
   str('')       str('01')      false    true    true   false   false   false
   str('')        str('1')      false    true    true   false   false   false
   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('+')       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('+')       true   false   false    true   false   false
 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')      false    true    true   false   false   false
   str('-')      str('01')      false    true    true   false   false   false
   str('1')       str('-')       true   false   false    true   false   false
 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')      false    true    true   false   false   false
   str('1')       str('0')       true   false   false    true   false   false
 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 > $c Загадка, если: $a не больше $c.

A&ltC   : float(NAN)  &gt  str('a')   &gt   str('')
A&ltC   : float(NAN)  &gt  str('a')   &gt   str('1')
A&ltC   : float(NAN)  &gt  str('a')   &gt   str('A')
A&ltC   : float(NAN)  &gt  str('a')   &gt   str('0')
A&ltC   : float(NAN)  &gt  str('1')   &gt   str('')
A&ltC   : float(NAN)  &gt  str('1')   &gt   str('0')
A&ltC   : float(NAN)  &gt  str('A')   &gt   str('')
A&ltC   : float(NAN)  &gt  str('A')   &gt   str('1')
A&ltC   : float(NAN)  &gt  str('A')   &gt   str('0')
A&ltC   : float(NAN)  &gt  str('0')   &gt   str('')
A&ltC   :   str('')   &gt float(NAN)  &gt   str('a')
A&ltC   :   str('')   &gt float(NAN)  &gt   str('1')
A&ltC   :   str('')   &gt float(NAN)  &gt   str('A')
A&ltC   :   str('')   &gt float(NAN)  &gt   str('0')
A&ltC   :  str('a')   &gt   str('')   &gt  float(NAN)
A&ltC   :  str('a')   &gt  str('1')   &gt  float(NAN)
A&ltC   :  str('a')   &gt  str('A')   &gt  float(NAN)
A&ltC   :  str('a')   &gt  str('0')   &gt  float(NAN)
A&ltC   :  str('0')   &gt   str('')   &gt  float(NAN)
A==C  : bool(true)  &gt   str('')   &gt  float(NAN)
A==C  : bool(true)  &gt   str('')   &gt float(-INF)
A==C  : bool(true)  &gt   str('')   &gt   int(-1)
A==C  : bool(true)  &gt   str('')   &gt  float(-1)
A==C  : bool(true)  &gt   array()   &gt  float(NAN)
A==C  : bool(true)  &gt   array()   &gt  float(INF)
A==C  : bool(true)  &gt   array()   &gt float(-INF)
A==C  : bool(true)  &gt   array()   &gt   str('a')
A==C  : bool(true)  &gt   array()   &gt    int(1)
A==C  : bool(true)  &gt   array()   &gt   float(1)
A==C  : bool(true)  &gt   array()   &gt   str('1')
A==C  : bool(true)  &gt   array()   &gt   str('A')
A==C  : bool(true)  &gt   array()   &gt   int(-1)
A==C  : bool(true)  &gt   array()   &gt  float(-1)
A==C  : bool(true)  &gt   int(0)    &gt float(-INF)
A==C  : bool(true)  &gt   int(0)    &gt   int(-1)
A==C  : bool(true)  &gt   int(0)    &gt  float(-1)
A==C  : bool(true)  &gt  str('0')   &gt  float(NAN)
A==C  : bool(true)  &gt  str('0')   &gt float(-INF)
A==C  : bool(true)  &gt  str('0')   &gt   int(-1)
A==C  : bool(true)  &gt  str('0')   &gt  float(-1)
A==C  : bool(true)  &gt  float(0)   &gt float(-INF)
A==C  : bool(true)  &gt  float(0)   &gt   int(-1)
A==C  : bool(true)  &gt  float(0)   &gt  float(-1)
A==C  :   int(1)    &gt  str('a')   &gt   str('1')
A==C  :   int(1)    &gt  str('A')   &gt   str('1')
A==C  :  float(1)   &gt  str('a')   &gt   str('1')
A==C  :  float(1)   &gt  str('A')   &gt   str('1')
A==C  :  str('a')   &gt  str('1')   &gt    int(0)
A==C  :  str('a')   &gt  str('1')   &gt   float(0)
A==C  :   str('')   &gt float(-INF) &gt  NULL(NULL)
A==C  :   str('')   &gt float(-INF) &gt bool(false)
A==C  :   str('')   &gt   int(-1)   &gt  NULL(NULL)
A==C  :   str('')   &gt   int(-1)   &gt bool(false)
A==C  :   str('')   &gt  float(-1)  &gt  NULL(NULL)
A==C  :   str('')   &gt  float(-1)  &gt bool(false)
A==C  :   array()   &gt float(NAN)  &gt  NULL(NULL)
A==C  :   array()   &gt float(NAN)  &gt bool(false)
A==C  :   array()   &gt float(INF)  &gt  NULL(NULL)
A==C  :   array()   &gt float(INF)  &gt bool(false)
A==C  :   array()   &gt float(-INF) &gt  NULL(NULL)
A==C  :   array()   &gt float(-INF) &gt bool(false)
A==C  :   array()   &gt  str('a')   &gt  NULL(NULL)
A==C  :   array()   &gt  str('a')   &gt bool(false)
A==C  :   array()   &gt   int(1)    &gt  NULL(NULL)
A==C  :   array()   &gt   int(1)    &gt bool(false)
A==C  :   array()   &gt  float(1)   &gt  NULL(NULL)
A==C  :   array()   &gt  float(1)   &gt bool(false)
A==C  :   array()   &gt  str('1')   &gt  NULL(NULL)
A==C  :   array()   &gt  str('1')   &gt bool(false)
A==C  :   array()   &gt  str('A')   &gt  NULL(NULL)
A==C  :   array()   &gt  str('A')   &gt bool(false)
A==C  :   array()   &gt  str('0')   &gt  NULL(NULL)
A==C  :   array()   &gt   int(-1)   &gt  NULL(NULL)
A==C  :   array()   &gt   int(-1)   &gt bool(false)
A==C  :   array()   &gt  float(-1)  &gt  NULL(NULL)
A==C  :   array()   &gt  float(-1)  &gt bool(false)
A==C  :   str('')   &gt float(NAN)  &gt bool(false)
A==C  :   str('')   &gt float(NAN)  &gt  NULL(NULL)
A==C  :  str('A')   &gt  str('1')   &gt    int(0)
A==C  :  str('A')   &gt  str('1')   &gt   float(0)
A==C  :   int(0)    &gt float(-INF) &gt  NULL(NULL)
A==C  :   int(0)    &gt float(-INF) &gt bool(false)
A==C  :   int(0)    &gt   int(-1)   &gt  NULL(NULL)
A==C  :   int(0)    &gt   int(-1)   &gt bool(false)
A==C  :   int(0)    &gt  float(-1)  &gt  NULL(NULL)
A==C  :   int(0)    &gt  float(-1)  &gt bool(false)
A==C  :  str('0')   &gt float(NAN)  &gt bool(false)
A==C  :  str('0')   &gt float(-INF) &gt bool(false)
A==C  :  str('0')   &gt   int(-1)   &gt bool(false)
A==C  :  str('0')   &gt  float(-1)  &gt bool(false)
A==C  :  float(0)   &gt float(-INF) &gt  NULL(NULL)
A==C  :  float(0)   &gt float(-INF) &gt bool(false)
A==C  :  float(0)   &gt   int(-1)   &gt  NULL(NULL)
A==C  :  float(0)   &gt   int(-1)   &gt bool(false)
A==C  :  float(0)   &gt  float(-1)  &gt  NULL(NULL)
A==C  :  float(0)   &gt  float(-1)  &gt bool(false)
A===C :  str('0')   &gt float(NAN)  &gt   str('0')
A===C :   str('')   &gt float(NAN)  &gt   str('')
A===C :  str('a')   &gt float(NAN)  &gt   str('a')
A===C :  str('1')   &gt float(NAN)  &gt   str('1')
A===C :  str('A')   &gt float(NAN)  &gt   str('A')

Смешное сравнение строк: 'Queen' > 'King' > 'Jack' > 'Ace'

Также проверьте таблицы сравнения типов PHP, охватывающие пары:

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

Проверьте различия между версиями PHP в прямом эфире. http://3v4l.org/MAfDu.

Ответ 3

После исправления второй части вашего вопроса я оставляю ответ на эту часть другим. Я просто хочу дать самый неожиданный ответ на первую часть вашего вопроса, т.е. Является ли пример операторов < и > непереходными. Вот оно.

Это все true:

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

Если < были транзитивными ($a < $b & и; $b < $c$a < $c), последняя строка была бы

"10" < "2"

но PHP пытается быть добрым (?!) и интерпретировать строки как числа, когда это возможно.

Оказывается, что из-за вышеперечисленной непереходности sort() может сортировать те же элементы в другой порядок в зависимости от их порядка ввода, even когда нет двух элементов == (и ни один элемент не является NAN). Я указал на это в комментарии для сортировки(), суть которого заключается в следующем:

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