PHP ist berühmt für sein Typ-Jonglieren. Ich muss zugeben, dass es mich verwirrt, und es fällt mir schwer, grundlegende logische / grundlegende Dinge in Vergleichen herauszufinden.
Zum Beispiel: Wenn $a > $b
wahr ist , und $b > $c
wahr ist , muss es bedeuten , dass $a > $c
ist immer wahr zu?
Nach der Grundlogik würde ich ja sagen, aber ich bin so verwirrt, dass ich PHP nicht wirklich vertraue. Vielleicht kann jemand ein Beispiel geben, wo dies nicht der Fall ist?
Ich frage mich auch bei den strengen Operatoren kleiner als und streng größer als (da ihre Bedeutung als streng beschrieben wird, was ich in der Vergangenheit nur aus den Gleichheitsvergleichen wusste), ob es einen Unterschied macht, wenn linke und rechte Operanden ausgetauscht werden streng ungleiche Werte:
# Precondition:
if ($a === $b) {
throw new Exception(
'Both are strictly equal - can not compare strictly for greater or smaller'
);
}
($a > $b) !== ($b > $a)
Für die meisten Typvergleichskombinationen sind diese größeren / kleineren Vergleichsoperatoren nicht dokumentiert, daher war das Lesen des Handbuchs in diesem Fall nicht wirklich hilfreich.
quelle
($a > $b) !== ($b < $a)
?Antworten:
Die Vergleichsoperatoren von PHP weichen in mehrfacher Hinsicht von den computerwissenschaftlichen Definitionen ab:
Um eine Äquivalenzbeziehung zu bilden,
==
muss sie reflexiv, symmetrisch und transitiv sein:Der PHP-
==
Operator ist nicht reflexiv , dh$a == $a
nicht immer wahr:Hinweis: Die Tatsache, dass ein Vergleich
NAN
immer durchgeführt wird,false
ist nicht spezifisch für PHP. Es ist vom IEEE 754-Standard für Gleitkomma-Arithmetik vorgeschrieben ( weitere Informationen ).Der PHP-
==
Operator ist symmetrisch , dh$a == $b
und$b == $a
immer gleich.PHP-
==
Operator ist nicht transitiv , dh aus$a == $b
und$b == $c
ist nicht folgt$a == $c
:Um eine Teilordnung zu bilden
<=
/>=
muss reflexiv, antisymmetrisch und transitiv sein:Der PHP-
<=
Operator ist nicht reflexiv , dh$a <= $a
nicht immer wahr (Beispiel wie für==
).Der PHP-
<=
Operator ist nicht antisymmetrisch , dh von$a <= $b
und$b <= $a
folgt nicht$a == $b
:Der PHP-
<=
Operator ist nicht transitiv , dh von$a <= $b
und$b <= $c
folgt nicht$a <= $c
(Beispiel wie für==
).Extra: Der PHP-
<=
Operator ist nicht vollständig , dh beides$a <= $b
und$b <= $a
kann falsch sein:Um eine strenge Teilordnung zu bilden
<
/>
muss irreflexiv, asymmetrisch und transitiv sein:Der PHP-
<
Operator ist irreflexiv , dh er$a < $a
ist niemals wahr. Beachten Sie, dass dies nur ab PHP 5.4 gilt . ZuvorINF < INF
ausgewertet zutrue
.Der PHP-
<
Operator ist nicht asymmetrisch , dh von$a < $b
folgt nicht!($b < $a)
(Beispiel wie für<=
nicht antisymmetrisch).Der PHP-
<
Operator ist nicht transitiv , dh von$a < $b
und$b < $c
folgt nicht$a < $c
:Extra: Der PHP-
<
Operator ist nicht trichotom , dh alle$a < $b
,$b < $a
und$a == $b
kann falsch sein (Beispiel wie für<=
nicht vollständig).Extra: PHP-
<
Operator kann sein kreisförmig , dh es ist möglich, dass$a < $b
,$b < $c
und$c < $a
:Hinweis: Im obigen Beispiel wird der Hinweis "Objekt der Klasse stdClass konnte nicht in double konvertiert werden" ausgelöst.
Unter PHP Sadness 52 - Vergleichsoperatoren finden Sie einige schöne Grafiken für die Vergleichsoperatoren von PHP .
Als letzte Anmerkung möchte ich darauf hinweisen , dass es zwei Gleichheiten , dass PHP tut Garantie ( im Gegensatz zu so ziemlich alles andere). Diese beiden gelten immer, einfach weil der Compiler das eine auf das andere reduziert:
quelle
($a > $b) and ($b > $c)
mit zu formulieren$a > $c
, obwohl die Dokumentation besagt, dass diese<
/>
Operatoren sagen, dass sie streng sind ?$a == $b
das dasselbe ist wie(type) $a === (type) $b
. Ein einfaches Beispiel dafür ist das"15" == "0xf"
, aber(int) "15" !== (int) "0xf"
. Und sowohl Vergleichs- als auch Casting-Regeln in PHP sind total verrückt ^^(int)"0xf"
Ganzzahl ausgewertet . Der Vergleich in diesem Beispiel verhält sich genau wie erwartet. Es ist das Casting, das hier verwirrend ist. Ich gebe zu, es war ein echtes Vergleichsproblem, aber es war ein Sonderfall, und es wurde gelöst, wie Sie betont haben. Tolle Antwort .. +10
0 !== 15
(INF < INF) === true
Es gibt keine streng identischen Vergleichsoperatoren (
>==
oder<==
) in PHP (mindestens in PHP 5.6.14) , aber es gibt einige Möglichkeiten , eine strenge Typprüfung zu erzwingen, bevor Größer / Niedriger überprüft wird:if (gettype($a) === gettype($b))
if ((string)$a === (string)$b)
if (($a . '') === ($b . ''))
Beachten Sie Folgendes:
INF
undNAN
sind vom Typfloat
unterieee754e
ist immer vom Typfloat
und niemalsinteger
selbst wenn die Anzahl klein istPHP_INT_MAX
automatisch in konvertiertfloat
INF
WertNULL
0
werden (gemäß Konvention) von Oktal in Dezimal konvertiert.0
in eine Ganzzahl enthalten, entfernt die führende0
Liste einiger exotischer Vergleiche:
Gleich, aber nicht identisch:
Niedriger und größer gleichzeitig?
Gleich UND identisch:
Niedriger oder größer:
$a > $b > $c
Rätsel, wenn:$a
nicht größer als ist$c
.Fun String Vergleich: 'Queen'
>
'King'>
'Jack'>
'Ace'Schauen Sie sich auch die PHP-Typvergleichstabellen an, die Paare abdecken:
isset()
undis_null()
if()
undempty()
==
vs.===
Überprüfen Sie die Unterschiede zwischen PHP-Versionen live unter. http://3v4l.org/MAfDu .
quelle
if ( (string)$a===(string)$b )
aber ist das nicht genau das Gleiche wieif ( (string)$a==(string)$b )
?(string)1==(string)'01'
->bool(true)
und für Typ-Jonglieren(1 . '')=='01'
->bool(true)
nicht genau das gleiche, als===
wenn Siebool(false)
auf beide Konten bekommen würdenINFINITY is equal to INFINITY which is mathematically incorrect!
ist eine ausgesprochen umstrittene Aussage. Beachten Sie auch, dass diesNaN
konventionell nicht größer, kleiner oder gleich irgendetwas in einer mir bekannten Programmiersprache ist.Nach Ihrer Korrektur des zweiten Teils Ihrer Frage überlasse ich die Antwort auf diesen Teil den anderen. Ich möchte nur die überraschendsten Antwort auf den ersten Teil Ihrer Frage geben, das heißt, ob es sich um ein Beispiel für die
<
und>
Betreiber intransitiv sein. Hier ist es.Das sind alles
true
:Wenn
<
transitiv wäre ($a < $b
∧$b < $c
⇒$a < $c
), wäre die letzte Zeileaber PHP versucht freundlich zu sein (?!) und Strings als Zahlen zu interpretieren, wann immer es möglich ist.
Es stellt sich heraus , dass aufgrund der oben intransitivity,
sort()
die Sortier können gleiche Elemente zu einer unterschiedlichen Reihenfolge auf ihre Eingabereihenfolge , abhängig, selbst wenn keine zwei Elemente sind==
(und kein Element ist NAN). Ich habe dies in einem Kommentar zu sort () hervorgehoben , dessen Kern ist:quelle
sort()
Tabelle, die auch für die praktischen Auswirkungen beim Schreiben des zugehörigen Blog-Beitrags The Greatest PHP Value ausgewählt wurde . Nochmals vielen Dank für Ihre Antwort.usort
wann immer möglich verwenden sollte?usort($arr, 'strcmp')
. Dies funktioniert (natürlich für Strings), ist aber am besten zu verwendensort($arr, SORT_STRING)
.