- PVSM.RU - https://www.pvsm.ru -
Четвертого апреля на stackoverflow появился вопрос [1], касающийся работы операторов сравнения в 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)
Для большинства комбинаций типов работа операторов сравнения больше/меньше не документирована.
Оператор сравнения в PHP в некоторых моментах отличается от канонического определения:
Отношение равенства должно быть рефлексивным, симметричным и транзитивным:
==
в PHP не рефлексивен, т. е. $a == $a
не всегда является истиной:
var_dump(NAN == NAN); // bool(false)
Примечание: То, что сравнение с участием NAN всегда является ложным не является особенностью PHP. Это поведение определено в стандарте IEEE 754 формата представления чисел с плавающей точкой (пояснения на stackoverflow [2]);
==
симметричен, т. е. $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
не всегда является истинным (см. пример для ==
);
<=
не антисимметричен, т. е. истинность выражений $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
(пример такой же, как и для оператора ==
).
<=
не является полным, т. е. и $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
является истинным;
<
не асимметричен, т. е. истинность выражения $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)
<
не трихотомичен, т. е. выражения $a < $b
, $b < $a
и $a == $b
могут быть ложными (пример такой же, как и для <=
);
<
может быть закольцованным, т. е. бывают случаи, когда $a < $b
, $b < $c
и $c < $a
являются истинными:
var_dump(INF < []); // bool(true)
var_dump([] < new stdClass); // bool(true)
var_dump(new stdClass < INF); // bool(true)
Примечание: Этот пример генерирует предупреждение «Object of class stdClass could not be converted to double» уровня notice.
Вы можете найти несколько восхитительных графиков в статье PHP Sadness 52 — Операторы сравнения [3].
И в конце я хочу отметить, что два равенства в PHP гарантированы (в отличии от почти всего остального) потому что интерпретатор приводит их к одному виду:
($a > $b) == ($b < $a)
($a >= $b) == ($b <= $a)
Автор: CultHero
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/php-2/31641
Ссылки в тексте:
[1] вопрос: http://stackoverflow.com/questions/15813490/php-type-juggling-and-strict-greater-lesser-than-comparisons
[2] пояснения на stackoverflow: http://stackoverflow.com/questions/1565164/what-is-the-rationale-for-all-comparisons-returning-false-for-ieee754-nan-values
[3] PHP Sadness 52 — Операторы сравнения: http://www.phpsadness.com/sad/52
[4] Источник: http://habrahabr.ru/post/176117/
Нажмите здесь для печати.