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

115

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)

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

hakre
источник
Думаю, вы хотите исправить эту строчку, чтобы она была ($a > $b) !== ($b < $a)?
Уолтер Тросс
ах, хорошо, я неправильно это понял. Придется исправить свой ответ соответственно. Забавно, что все эти люди пишут трактаты вместо ответов и не читают внимательно ваш вопрос ...
Уолтер Тросс,

Ответы:

208

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

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

  • ==Оператор 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)

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

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

  • Дополнительно: 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)
NikiC
источник
2
Вау, хороший ответ. Таким образом, невозможно сформулировать логические выражения с помощью PHP, например ($a > $b) and ($b > $c)с, $a > $cдаже если в документации указано, что эти операторы </ >говорят, что они строгие ?
hakre
26
Операторы IMHO действительно следуют математическим правилам, но только при работе с одними и теми же типами данных. Приведение типов - вот что действительно создает путаницу здесь (и во многих других ситуациях). При сравнении чисел и строк и специальных значений преобразования типов выполняются до операторов, поэтому, строго говоря, операторы сравнения не сбивают с толку, приведение типов ...
ivanhoe 06
6
@ ivanhoe011 На самом деле: оба варианта :) Правила сравнения PHP и правила приведения типов PHP отличаются , вы не можете просто сказать, что $a == $bэто то же самое, что и (type) $a === (type) $b. Простой пример - это "15" == "0xf", но (int) "15" !== (int) "0xf". И правила сравнения и приведения в PHP совершенно безумны ^^
NikiC 06
3
@NikiC: (int)"0xf"оценивается как целое 0, так что, конечно 0 !== 15. Сравнение в этом примере ведет себя точно так, как ожидалось. Здесь сбивает с толку кастинг. Признаюсь, это (INF < INF) === trueбыла настоящая проблема сравнения, но это был особый случай, и он был решен, как вы отметили. Отличный ответ .. +1
FtDRbwLXw6 08
1
Я не обязательно виню разработчиков PHP за некоторые из решений, которые имели смысл в отношении приведения типов в то время ... но я чувствую, что они должны были заметить результаты этих вариантов дизайна и сразу же понять, что выбор был явно неправильным. Самый очевидный пример - это комментарий @ ravz.
Чад
88

В 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ниже
  • Некоторая Бесконечность равна некоторой другой Бесконечности (начиная с PHP 5.4)
  • Научная запись eвсегда типичная float, и никогда, integerдаже если число невелико.
  • Переходящие целые числа PHP_INT_MAXавтоматически преобразуются вfloat
  • Плавает над границами системы, получает INFзначение
  • Неопределенные переменные имеют тип и значение NULL
  • Целые числа, которым предшествует 0, преобразуются из восьмеричного в десятичное (по соглашению)
  • Преобразование строк, содержащих целое число с ведущим числом, 0 в целое число удаляет ведущее число0

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

Очень странно:
     $ 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) ложь ложь ложь ложь ложь ложь
  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) ложь ложь правда правда правда ложь
   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) ложь ложь правда правда правда правда
 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) истина ложь ложь истина ложь ложь
  NULL (NULL) float (1) false true true false false false
  float (INF) NULL (NULL) истина ложь ложь истина ложь ложь
  float (NAN) NULL (NULL) истина ложь ложь истина ложь ложь
  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) истина ложь ложь истина ложь ложь
   array () int (0) истина ложь ложь истина ложь ложь
   array () int (1) true false false true false false
   array () str ("\ 0") истина ложь ложь истина ложь ложь
   str ('') array () false true true false false false
   array () str ('+') истина ложь ложь истина ложь ложь
   array () str ('-') true false false true false false
   array () str ('0') true false false true false false
   array () str ('01 ') истина ложь ложь истина ложь ложь
   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) истина ложь ложь истина ложь ложь
   float (1) bool (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) истина ложь ложь истина ложь ложь
 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) истина ложь ложь истина ложь ложь
 float (-INF) int (-1) ложь истина правда ложь ложь ложь
 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) истина ложь ложь истина ложь ложь
  float (INF) float (0) истина ложь ложь истина ложь ложь
   float (0) int (-1) истина ложь ложь истина ложь ложь
    int (1) float (0) истина ложь ложь истина ложь ложь
   float (0) str ('01 ') false true true false false false
   str ('1') float (0) истина ложь ложь истина ложь ложь
  float (INF) float (1) истина ложь ложь истина ложь ложь
   float (1) int (-1) истина ложь ложь истина ложь ложь
   float (1) int (0) истина ложь ложь истина ложь ложь
   float (1) str ("\ 0") истина ложь ложь истина ложь ложь
   str ('') float (1) false true true false false false
   float (1) str ('+') истина ложь ложь истина ложь ложь
   float (1) str ('-') истина ложь ложь истина ложь ложь
   float (1) str ('0') истина ложь ложь истина ложь ложь
   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 ложь
  float (INF) int (-1) истина ложь ложь истина ложь ложь
  float (INF) int (0) истина ложь ложь истина ложь ложь
  float (INF) int (1) истина ложь ложь истина ложь ложь
  float (INF) str ("\ 0") истина ложь ложь истина ложь ложь
  float (INF) str ('') истина ложь ложь истина ложь ложь
  float (INF) str ('+') истина ложь ложь истина ложь ложь
  float (INF) str ('-') true false false true false false
  float (INF) str ('0') true false false true false false
  float (INF) str ('01 ') истина ложь ложь истина ложь ложь
  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) истина ложь ложь истина ложь ложь
    int (1) int (-1) истина ложь ложь истина ложь ложь
  str ("\ 0") int (-1) истина ложь ложь истина ложь ложь
   str ('') int (-1) истина ложь ложь истина ложь ложь
   str ('+') int (-1) истина ложь ложь истина ложь ложь
   str ('-') int (-1) истина ложь ложь истина ложь ложь
   str ('0') int (-1) истина ложь ложь истина ложь ложь
   int (-1) str ('01 ') ложь истина правда ложь ложь ложь
   str ('1') int (-1) истина ложь ложь истина ложь ложь
 str ('false') int (-1) истина ложь ложь истина ложь ложь
 str ('text') int (-1) истина ложь ложь истина ложь ложь
 str ('true') int (-1) истина ложь ложь истина ложь ложь
    int (1) int (0) истина ложь ложь истина ложь ложь
    int (0) str ('01 ') ложь истина правда ложь ложь ложь
   str ('1') int (0) истина ложь ложь истина ложь ложь
    int (1) str ("\ 0") истина ложь ложь истина ложь ложь
   str ('') int (1) false true true false false false
    int (1) str ('+') истина ложь ложь истина ложь ложь
    int (1) str ('-') истина ложь ложь истина ложь ложь
    int (1) str ('0') истина ложь ложь истина ложь ложь
    int (1) str ('false') истина ложь ложь истина ложь ложь
 str ('текст') int (1) false true true false false false
 str ('true') int (1) false true true false false ложь
   str ('') str ("\ 0") false true true false false false
   str ('+') str ("\ 0") истина ложь ложь истина ложь ложь
   str ('-') str ("\ 0") истина ложь ложь истина ложь ложь
  str ("\ 0") str ('0') false true true false false false
  str ("\ 0") str ('01 ') false true true false false false
   str ('1') str ("\ 0") истина ложь ложь истина ложь ложь
 str ('false') str ("\ 0") true false false true false false
 str ('text') str ("\ 0") истина ложь ложь истина ложь ложь
 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 ложь
   str ('') str ('1') false true true 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 ложь
   str ('-') str ('+') истина ложь ложь истина ложь ложь
   str ('+') str ('0') false true true false false ложь
   str ('+') str ('01 ') false true true false false ложь
   str ('1') str ('+') истина ложь ложь истина ложь ложь
 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 ('-') истина ложь ложь истина ложь ложь
 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 ложь
   str ('1') str ('0') истина ложь ложь истина ложь ложь
 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 <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 (истина)> str ('')> float (NAN)
A == C: bool (истина)> str ('')> float (-INF)
A == C: bool (истина)> str ('')> int (-1)
A == C: bool (истина)> str ('')> float (-1)
A == C: bool (истина)> массив ()> float (NAN)
A == C: bool (истина)> массив ()> float (INF)
A == C: bool (истина)> массив ()> float (-INF)
A == C: bool (истина)> массив ()> str ('a')
A == C: bool (истина)> массив ()> int (1)
A == C: bool (истина)> массив ()> float (1)
A == C: bool (истина)> массив ()> str ('1')
A == C: bool (истина)> массив ()> str ('A')
A == C: bool (истина)> массив ()> int (-1)
A == C: bool (истина)> массив ()> float (-1)
A == C: bool (истина)> int (0)> float (-INF)
A == C: bool (истина)> int (0)> int (-1)
A == C: bool (истина)> int (0)> float (-1)
A == C: bool (истина)> str ('0')> float (NAN)
A == C: bool (истина)> str ('0')> float (-INF)
A == C: bool (истина)> str ('0')> int (-1)
A == C: bool (истина)> 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: интервал (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 (ложь)
A == C: str ('')> int (-1)> NULL (NULL)
A == C: str ('')> int (-1)> bool (ложь)
A == C: str ('')> float (-1)> NULL (NULL)
A == C: str ('')> float (-1)> bool (ложь)
A == C: array ()> float (NAN)> NULL (NULL)
A == C: массив ()> float (NAN)> bool (false)
A == C: array ()> float (INF)> NULL (NULL)
A == C: array ()> float (INF)> bool (ложь)
A == C: array ()> float (-INF)> NULL (NULL)
A == C: array ()> float (-INF)> bool (ложь)
A == C: array ()> str ('a')> NULL (NULL)
A == C: массив ()> str ('a')> bool (ложь)
A == C: массив ()> int (1)> NULL (NULL)
A == C: массив ()> int (1)> bool (ложь)
A == C: array ()> float (1)> NULL (NULL)
A == C: array ()> float (1)> bool (ложь)
A == C: array ()> str ('1')> NULL (NULL)
A == C: массив ()> str ('1')> bool (false)
A == C: array ()> str ('A')> NULL (NULL)
A == C: массив ()> str ('A')> bool (ложь)
A == C: array ()> str ('0')> NULL (NULL)
A == C: array ()> int (-1)> NULL (NULL)
A == C: массив ()> int (-1)> bool (ложь)
A == C: array ()> float (-1)> NULL (NULL)
A == C: array ()> float (-1)> bool (ложь)
A == C: str ('')> float (NAN)> bool (ложь)
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 (ложь)
A == C: int (0)> int (-1)> NULL (NULL)
A == C: int (0)> int (-1)> bool (ложь)
A == C: int (0)> float (-1)> NULL (NULL)
A == C: int (0)> float (-1)> bool (ложь)
A == C: str ('0')> float (NAN)> bool (ложь)
A == C: str ('0')> float (-INF)> bool (ложь)
A == C: str ('0')> int (-1)> bool (ложь)
A == C: str ('0')> float (-1)> bool (ложь)
A == C: float (0)> float (-INF)> NULL (NULL)
A == C: float (0)> float (-INF)> bool (ложь)
A == C: float (0)> int (-1)> NULL (NULL)
A == C: float (0)> int (-1)> bool (ложь)
A == C: float (0)> float (-1)> NULL (NULL)
A == C: float (0)> float (-1)> bool (ложь)
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')

Забавное сравнение строк: "дама", >"король", >"валет", >"туз"

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

  • isset() и is_null()
  • if() и empty()
  • логическое ==vs.===

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

CSᵠ
источник
26
+1 не говоря уже о прокручиваемых "таблицах" с фиксированными заголовками столбцов - отличная идея;)
hakre 06
Нужно ли использовать строгий оператор при приведении типов? Я имею в виду, что вы написали, if ( (string)$a===(string)$b )но разве это не то же самое, что if ( (string)$a==(string)$b )?
Войткус
@Voitcus: да, как для приведений типов (string)1==(string)'01'->, так bool(true)и для манипуляций с типами (1 . '')=='01'-> bool(true)не совсем то же самое, что и ===при использовании bool(false)обоих учетных записей
CS
1
Одна придирка: восьмеричные значения не «конвертируются при назначении», они интерпретируются компилятором, который должен преобразовать ASCII в фактические двоичные числа.
IMSoP
INFINITY is equal to INFINITY which is mathematically incorrect!это явно спорно утверждение. Также обратите внимание, что NaNпо соглашению не больше, меньше или равно чему-либо на любом языке программирования, о котором я знаю.
DaveRandom
22

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

Это все 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" )
Уолтер Тросс
источник
1
предыдущий комментарий относится к части ответа (относящейся ко второй части вопроса), которую я тем временем удалил
Уолтер Тросс
Удалил это сейчас;) И хорошая новая sort()таблица, выбранная также для практических целей при написании соответствующего сообщения в блоге The Greatest PHP Value . Еще раз спасибо за ваш ответ.
hakre 08
Означает ли это, что нужно использовать по usortвозможности?
Войткус
2
@Voitcus: Я думаю, ты имеешь в виду usort($arr, 'strcmp'). Это работает (конечно, для строк), но лучше использовать sort($arr, SORT_STRING).
Уолтер Тросс
@WalterTross Я имею в виду всегда использовать свою собственную функцию (не только для строк), чтобы гарантировать, что она всегда верна
Войткус