- 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/
Нажмите здесь для печати.