Жонглирование типов и (строгое) большее / меньшее сравнение в PHP

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

Например: если $a > $b это правда и $b > $c верно, это должно означать, что $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)

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

3 ответа

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

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

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

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

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

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

  • РНР == оператор не транзитивен, т.е. $a == $b а также $b == $c не следует $a == $c:

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

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

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

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

    var_dump(NAN <= "foo"); // bool(true)
    var_dump("foo" <= NAN); // bool(true)
    var_dump(NAN == "foo"); // bool(false)
    
  • РНР <= оператор не транзитивен, т.е. $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)
    

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

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

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

  • РНР < оператор не транзитивен, т.е. $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 может быть ложным (пример такой же, как для <= не будучи тотальным).

  • Дополнительно: 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)

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

  1. Проверьте оба типа переменных с if (gettype($a) === gettype($b))
  2. Заставьте нужного вам типа, например. if ((string)$a === (string)$b)
  3. Заставьте нужного типа жонглировать, например. if (($a . '') === ($b . ''))

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

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

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

Очень странно:
     $ 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) ложный ложный ложный ложный ложный ложный ложный ложный
  float (NAN) float (1) ложный ложный ложный ложный ложный ложный ложный ложный
  float(NAN)     float(INF) ложный ложный ложный ложный ложный ложный ложный ложный
  float (NAN) float (NAN) ложный ложный ложный ложный ложный ложный ложный ложный
  float(NAN)      int(-1)       false   false   false   false   false   false
  false
  float(NAN)       int(0)       false   false   false   false   false   false
  false
  float (NAN) int (1) false false false false false false false

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

     $ 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 false true    true    true   false
  NULL(NULL)      float(0)      false   false false true    true    true   false
  NULL(NULL)       int(0)       false   false false true    true    true   false
  NULL(NULL)      str('')       false   false    true    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 false true    true    true   false
 bool(false)      str('0') false false   false    true    true    true   false
 float(-INF)     bool(true)     false   false    true    true    true true false
  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 false
  bool(true)       int(1)       false   false 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 false true    true    true   false
  bool(true)     str('01')      false   false false true    true    true   false
  bool(true)      str('1')      false   false false true    true    true   false
  bool(true)    str('false')    false   false false true    true    true   false
 str('text')     bool(true)     false   false false true    true    true   false
 str('true')     bool(true)     false   false false 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 false true true true false 
    str ('-') float (0) false false false true true true false 
    str ('0') float (0) false false false true true true false 
  str ('false') float (0) false false false true true true false 
  str ('text') float (0) false false false true true true false 
  str ('true') float (0) false false false true true true false 
     int (1) float (1) false false true true true true false 
    float (1) str ('01 ') false false false true true true false 
    float (1) str ('1') false false false true true true false 
   str ("\ 0") int (0) false false false true true true false 
    str ('') int (0) false false true true true true false 
    str ('+') int (0) false false false true true true false 
    str ('-') int (0) false false false true true true false 
     int (0) str ('0') false false false true true true false 
  str ('false') int (0) false false false true true true false 
  str ('text') int (0) false false false true true true false 
  str ('true') int (0) false false false true true true false 
     int (1) str ('01 ') false false false true true true false 
     int (1) str ('1') false false false true true true false 
    str ('1')      str('01') false false true true true true false

Нижний и Большой одновременно?

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

Равный И идентичный:

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

Ниже или выше:

     $ VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b
  NULL (NULL) bool (true) false true true false false false false float(-INF)     NULL(NULL)      true   false   false    true   false   false false NULL(NULL)      float(1)      false    true    true true false false   false   false
  float(INF)     NULL(NULL)) true   false   false    true   false   false
  float(NAN)     NULL(NULL)      true   false   false    true   false   false false NULL(NULL)      int(-1)       false    true    true true false   false   false
  NULL(NULL)       int(1)       false    true    true false   false   false   false
  NULL(NULL)     str("\0")      false    true    true true false   false   false
  NULL(NULL)      str('+')      false    true    true   false   false   false
  NULL(NULL)      str('-')      false    true    true   false   false   false false NULL(NULL)      str('0')      false    true    true   false   false   false
  NULL(NULL)     str('01')      false    true    true true false   false   false
  NULL(NULL)      str('1')      false    true    true   false   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 false array () bool () true) false true true false false false false (-INF)      array()       false    true    true true false false false array () flo at (0) true false false true false false array () float (1) true false false false true   false   false
  float(INF)      array()       false    true    true true false   false   false
  float(NAN)      array()       false    true    true   false   false   false false array()        int(-1)        true   false   false    true   false   false
   array()         int(0)        true   false   false    true   false   false false array()         int(1)        true false   false   false    true   false   false
   array()       str("\0")       true   false   false    true   false   false
   str('')        array()       false    true    true   false   false   false false array()        str('+')       true   false   false false true   false   false
   array()        str('-')       true   false   false false true false false массив ()        str('0')       true   false   false false   false   false
   array()       str('01')       true   false   false false true   false   false
   array()        str('1')       true   false   false false   false   false
   array()      str('false')     true   false   false    true   false   false
   array()      str('text')      true   false   false false false   false   false
   array()      str('true')      true   false   false    true   false   false false bool(true)    bool(false)      true false   false   false    true   false   false
 float(-INF)    bool(false)      true   false   false    true   false   false
   false float(1)     bool(false)) true   false   false    true   false   false
  float(INF)    bool(false)      true   false   false false true   false   false
  float(NAN)    bool(false)      true   false   false    true   false   false   false
 bool(false)      int(-1)       false    true    true   false   false   false false int(1)      bool(false)      true   false   false false   false   false
 bool(false)     str("\0")      false    true    true   false   false   false   false
 bool(false)      str('+')      false    true    true true false false false bool (false)) str('-')      false    true    true   false   false   false
 bool(false)     str('01')      false    true    true true false   false   false
   str('1')     bool(false)      true   false   false false true   false   false
 bool(false)    str('false')    false    true    true   false   false   false
 str('text')    bool(false)      true   false   false false true   false   false
 str('true')    bool(false)      true   false   false false false   false   false
  bool(true)      float(0)) true   false   false    true   false   false
  bool(true)       int(0)        true   false   false false true   false   false
   str('')       bool(true)     false    true    true true false   false   false
  bool(true)      str('0')       true false   false   false    true   false   false
 float(-INF)      float(0)      false    true    true true false false   false   false
 float(-INF)      float(1)      false правда верно ложно ложно ложно с плавающей запятой (INF) поплавок (-INF) верно ложно ложно истинно ложно ложно с плавающей запятой (-INF)      int(-1) ложно верно истина ложно ложно с плавающей запятой (-INF)       int(0) ложно истинно истинно ложно false   false
 float(-INF)       int(1)       false    true    true false   false   false   false
 float(-INF)     str("\0")      false    true    true true false   false   false
 float(-INF)      str('')       false    true    true true false   false   false
 float(-INF)      str('+')      false    true    true   false   false   false
 false (-INF)      str('-')      false    true    true true false   false   false
 float(-INF)      str('0')      false    true    true   false   false   false
 float(-INF)     str('01')      false    true    true true false   false   false
 float(-INF)      str('1')      false    true    true   false   false   false
 false (-INF)    str('false')    false    true    true   false   false   false
 float(-INF)    str('text')     false    true    true true false   false   false
 float(-INF)    str('true')     false    true    true   false   false   false
   false float(1)       float(0)       true   false   false false true   false   false
  float(INF)      float(0)       true   false   false false false   false   false
   float(0)       int(-1)        true   false   false    true   false   false false int(1)        float(0)       true   false   false истина ложь ложь float(0)      str('01') ложь истина true false ложь false
   str('1')       float(0) истина ложь ложь истина ложь ложь float(INF)      float(1) истина ложь ложь true false ложь float(1)       int(-1)        true   false   false    true   false   false
   false float(1)        int(0)        true   false   false    true false   false   false
   float(1)      str("\0")       true   false   false false false false str ('') float (1) false true    true    true   false   false   false
   float(1)       str('+')       true   false   false false true   false   false
   float(1)       str('-')       true   false   false false   false   false
   float(1)       str('0')       true   false   false    true   false   false
   float(1)     str('false')     true   false   false    true   false   false false str('text')      float(1)      false    true    true true false false false str (' true ') float (1) ложь истина истинно ложно ложно ложно с плавающей запятой (INF)      int(-1) истина ложно ложно истинно ложно с ошибкой float(INF)       int(0) истина ложно ложно верно истина ложно с ошибкой float(INF)       int(1) истина ложно ложно истинно ложно ложно с плавающей точкой (INF)     str("\0")       true   false   false false   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 false true   false   false
  float(INF)      str('0')       true   false   false    true   false   false
  float(INF)     str('01')       true   false   false false true   false   false
  float(INF)      str('1')       true   false   false    true   false   false
  false float(INF)    str('false')     true   false   false false false   false   false
  float(INF)    str('text')      true   false   false    true true false   false
  float(INF)    str('true')      true   false   false false false   false   false
    int(0)        int(-1)        true   false   false false false   false   false
    int(1)        int(-1)        true   false   false false false   false   false
  str("\0")       int(-1)        true   false   false    true   false   false false str('')        int(-1)        true   false   false false true false   false   false
   str('+')       int(-1)        true   false   false false true   false   false
   str('-')       int(-1)        true   false   false    true   false   false false str('0')       int(-1)        true   false   false false true false   false   false
   int(-1)       str('01')      false    true    true true false   false   false
   str('1')       int(-1)        true   false   false    true   false   false false str('false')     int(-1)        true   false   false false true   false   false
 str('text')      int(-1)        true   false   false false   false   false
 str('true')      int(-1)        true   false   false    true   false   false false int(1)         int(0)        true   false   false    true   false   false false int(0)       str('01')      false    true    true true false   false   false
   str('1')        int(0)        true false   false   false    true   false   false
    int(1)       str("\0")       true   false   false    true   false   false false str ('') int (1) false true true false   false   false   false
    int(1)        str('+')       true   false   false false true   false   false
    int(1)        str('-')       true   false   false false   false   false
    int(1)        str('0')       true   false   false    true   false   false false int (1) str ('false') true false false false true false false str (' text ') int (1) false true true false false false false str (' true ') int (1) false true    true    true   false   false   false
   str('')       str("\0")      false    true    true true false   false   false
   str('+')      str("\0")       true   false   false false   false   false
   str('-')      str("\0")       true   false   false false   false   false
  str("\0")       str('0')      false    true    true   false   false   false
  str("\0")      str('01')      false    true    true true false   false   false
   str('1')      str("\0")       true   false   false false true   false   false
 str('false')    str("\0")       true   false   false false   false   false
 str('text')     str("\0")       true   false   false se true   false   false
 str('true')     str("\0")       true   false   false false true false false str ('+) str (' + ') false true true true false false false str (' ') str (' - ') ложь верно истина ложно ложно ложно стр ') false true true false false false str (' ') str (' false ') false true true true false false false str (' ') str (' text ') false true true true false false false str (' ') str (' true ') false true true false false false str (' - ') str (' + ') true false false false true false false str (' + ') str (' 0 ') false true true false false false false str (' + ')) str('01')      false    true    true   false   false   false
   str('1')       str(' + ') true false false true false false false str (' false ') str (' + ') true false false false   false   false
 str('text')      str('+') true false false false false false false str ('true') str ('+') true false false false true false false str ('-')      str('0') false true true true false false false str ('-')      str('01') false true true true false false false false str (' 1 ') str (' - ') true fa lse false true false false str ('false') str ('-') true false false false false   false   false
 str('text')      str('-') true false false false false false false str ('true') str (' - ') true false false true false false str (' 0 ')      str('01') false true true true false false false str ('1')      str('0') true false 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 false str ('true')      str('0') true false false true false false false str ('false')      str('01') true false false false true false false str (' text ')      str('01') true false false false true false false str ('true')      str('01') true false false false true false false str ('1') str ('false') false true true true false   false   false
 str('text')      str('1') true false false false true false false str ('true') str ('1')) true false false true false false str ('текст') str ('false') true false false true false false false str ('true') str ('false') true false false false false false false str ('true') str ('текст') true false false true false false false 

$a > $b > $c Загадка, когда: $a не больше чем $c ,

A  str ('a')> str ('')
A  str ('a')> str ('1')
A  str ('a')> str ('A')
A  str ('a')> str ('0')
A  str ('1')> str ('')
A  str ('1')> str ('0')
A  str ('A')> str ('')
A  str ('A')> str ('1')
A  str ('A')> str ('0')
A  str ('0')> str ('')
A  float (NAN)> str ('a')
A  float (NAN)> str ('1')
A  float (NAN)> str ('A')
A  float (NAN)> str ('0')
A  str ('')> float (NAN)
A  str ('1')> float (NAN)
A  str ('A')> float (NAN)
A  str ('0')> float (NAN)
A  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')

Веселое сравнение строк: "Королева" > 'Король' > 'Джек' > 'Ace'

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

  • isset() а также is_null()
  • if() а также empty()
  • логический == против ===

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

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

Это все true:

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

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

"10" < "2"

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

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

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" )
Другие вопросы по тегам