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)
Для большинства комбинаций сравнения типов эти операторы большего / меньшего сравнения не задокументированы, поэтому чтение руководства в данном случае не помогло.
($a > $b) !== ($b < $a)
?Ответы:
Операторы сравнения PHP отклоняются от компьютерно-научных определений по нескольким причинам:
Чтобы образовать эквивалентность, отношение
==
должно быть рефлексивным, симметричным и транзитивным:==
Оператор PHP не является рефлексивным , т.е.$a == $a
не всегда верно:Примечание. Тот факт, что любое сравнение
NAN
всегдаfalse
проводится не только в PHP. Это предусмотрено стандартом IEEE 754 для арифметики с плавающей запятой ( подробнее ).РНР
==
оператор симметричен , то есть$a == $b
и$b == $a
всегда одинаковы.РНР
==
оператор не является транзитивным , то есть от$a == $b
и$b == $c
вовсе не следует$a == $c
:Чтобы создать частичный порядок,
<=
/>=
должно быть рефлексивным, антисимметричным и транзитивным:<=
Оператор PHP не рефлексивен , т.е.$a <= $a
не всегда верен (пример такой же, как для==
).<=
Оператор PHP не является антисимметричным , т. Е. Из$a <= $b
и$b <= $a
не следует$a == $b
:<=
Оператор PHP не является транзитивным , т.е. от$a <= $b
и$b <= $c
не следует$a <= $c
(Пример такой же, как для==
).Дополнительно: PHP,
<=
оператор не общее , то есть как$a <= $b
и$b <= $a
может быть ложным:Чтобы создать строгий частичный порядок,
<
/>
должно быть иррефлексивным, асимметричным и транзитивным:<
Оператор PHP нерефлексивен , то$a < $a
есть никогда не верен. Обратите внимание, что это верно только для PHP 5.4 . РанееINF < INF
оценивался вtrue
.<
Оператор PHP не является асимметричным , т.е. from$a < $b
не следует!($b < $a)
(Пример такой же, как для<=
несимметричного).<
Оператор PHP не является транзитивным , т.е. из$a < $b
и$b < $c
не следует$a < $c
:Дополнительно:
<
оператор PHP не является трихотомическим , то есть целиком$a < $b
,$b < $a
и$a == $b
может быть ложным (пример такой же, как и для<=
неполного).Дополнительно: PHP,
<
оператор может быть круговым , то есть вполне возможно , что$a < $b
,$b < $c
и$c < $a
:Примечание. В приведенном выше примере выдается уведомление «Объект класса stdClass не может быть преобразован в двойной».
Вы можете найти несколько хороших графиков для операторов сравнения PHP на PHP Sadness 52 - Операторы сравнения .
В качестве последней ноты, я хочу отметить, что существует два равенства , что PHP делает гарантию ( в отличие от почти всего остального). Эти два значения всегда выполняются просто потому, что компилятор сводит одно к другому:
источник
($a > $b) and ($b > $c)
с,$a > $c
даже если в документации указано, что эти операторы<
/>
говорят, что они строгие ?$a == $b
это то же самое, что и(type) $a === (type) $b
. Простой пример - это"15" == "0xf"
, но(int) "15" !== (int) "0xf"
. И правила сравнения и приведения в PHP совершенно безумны ^^(int)"0xf"
оценивается как целое0
, так что, конечно0 !== 15
. Сравнение в этом примере ведет себя точно так, как ожидалось. Здесь сбивает с толку кастинг. Признаюсь, это(INF < INF) === true
была настоящая проблема сравнения, но это был особый случай, и он был решен, как вы отметили. Отличный ответ .. +1В PHP нет строго идентичных операторов сравнения (
>==
или<==
) (по крайней мере , в PHP 5.6.14) , но есть несколько способов принудительно выполнить строгую проверку типа перед проверкой Greater / Lower:if (gettype($a) === gettype($b))
if ((string)$a === (string)$b)
if (($a . '') === ($b . ''))
Обратите внимание, что:
INF
иNAN
относятся к типуfloat
нижеIEEE754e
всегда типичнаяfloat
, и никогда,integer
даже если число невелико.PHP_INT_MAX
автоматически преобразуются вfloat
INF
значениеNULL
0
, преобразуются из восьмеричного в десятичное (по соглашению)0
в целое число удаляет ведущее число0
Список некоторых экзотических сравнений:
Равные, но не идентичные:
Низшее и Высшее одновременно?
Равно И идентично:
Ниже или выше:
$a > $b > $c
Загадка, когда:$a
не больше$c
.Забавное сравнение строк: "дама",
>
"король",>
"валет",>
"туз"Также ознакомьтесь с таблицами сравнения типов PHP, охватывающими пары:
isset()
иis_null()
if()
иempty()
==
vs.===
Проверить различия между версиями PHP можно на сайте. http://3v4l.org/MAfDu .
источник
if ( (string)$a===(string)$b )
но разве это не то же самое, чтоif ( (string)$a==(string)$b )
?(string)1==(string)'01'
->, такbool(true)
и для манипуляций с типами(1 . '')=='01'
->bool(true)
не совсем то же самое, что и===
при использованииbool(false)
обоих учетных записейINFINITY is equal to INFINITY which is mathematically incorrect!
это явно спорно утверждение. Также обратите внимание, чтоNaN
по соглашению не больше, меньше или равно чему-либо на любом языке программирования, о котором я знаю.После того, как вы исправили вторую часть вашего вопроса, я оставляю ответ на эту часть другим. Я просто хочу , чтобы дать наиболее неожиданный ответ на первую часть вашего вопроса, то есть, есть ли пример
<
и>
операторы являются непереходным. Вот.Это все
true
:Если бы
<
были транзитивными ($a < $b
∧$b < $c
⇒$a < $c
), последняя строка была быно PHP старается быть добрым (?!) и всегда интерпретировать строки как числа.
Оказывается, что из-за вышеупомянутой непереходности
sort()
можно сортировать одни и те же элементы в другом порядке в зависимости от их порядка ввода, даже если нет двух элементов==
(и ни один элемент не является NAN). Я указал на это в комментарии к sort () , суть которого такова:источник
sort()
таблица, выбранная также для практических целей при написании соответствующего сообщения в блоге The Greatest PHP Value . Еще раз спасибо за ваш ответ.usort
возможности?usort($arr, 'strcmp')
. Это работает (конечно, для строк), но лучше использоватьsort($arr, SORT_STRING)
.