PHP est célèbre pour son jonglage de types. Je dois admettre que cela me laisse perplexe, et j'ai du mal à trouver des éléments logiques / fondamentaux de base dans les comparaisons.
Par exemple: si $a > $b
est vrai et $b > $c
est vrai, cela signifie-t-il que $a > $c
c'est toujours vrai aussi?
En suivant une logique de base, je dirais oui, mais je suis perplexe, je ne fais pas vraiment confiance à PHP. Peut-être que quelqu'un peut donner un exemple où ce n'est pas le cas?
De plus, je me demande avec les opérateurs stricts inférieurs à et stricts supérieurs à (car leur signification est décrite comme strictement que je ne connaissais que dans le passé grâce aux comparaisons d'égalité) si cela fait une différence si les opérandes gauche et droit sont échangés avec valeurs strictement inégales:
# Precondition:
if ($a === $b) {
throw new Exception(
'Both are strictly equal - can not compare strictly for greater or smaller'
);
}
($a > $b) !== ($b > $a)
Pour la plupart de toutes les combinaisons de comparaison de types, ces opérateurs de comparaison plus grands / plus petits ne sont pas documentés, la lecture du manuel n'a donc pas été vraiment utile dans ce cas.
($a > $b) !== ($b < $a)
?Réponses:
Les opérateurs de comparaison PHP s'écartent des définitions informatiques et scientifiques de plusieurs manières:
Pour constituer une relation d'équivalence
==
doit être réflexive, symétrique et transitive:L'
==
opérateur PHP n'est pas réflexif , c'est$a == $a
-à- dire n'est pas toujours vrai:Remarque: le fait que toute comparaison impliquant
NAN
soit toujoursfalse
n'est pas spécifique à PHP. Il est mandaté par la norme IEEE 754 pour l'arithmétique à virgule flottante ( plus d'informations ).L'
==
opérateur PHP est symétrique , c'est$a == $b
-à- dire et$b == $a
est toujours le même.L'
==
opérateur PHP n'est pas transitif , c'est-à-dire de$a == $b
et$b == $c
ne suit pas$a == $c
:Pour constituer un ordre partiel
<=
/>=
doit être réflexif, antisymétrique et transitif:L'
<=
opérateur PHP n'est pas réflexif , c'est-à$a <= $a
- dire n'est pas toujours vrai (exemple identique à pour==
).L'
<=
opérateur PHP n'est pas anti-symétrique , c'est-à-dire de$a <= $b
et$b <= $a
ne suit pas$a == $b
:L'
<=
opérateur PHP n'est pas transitif , c'est-à-dire from$a <= $b
et$b <= $c
ne suit pas$a <= $c
(exemple identique à pour==
).Extra: l'
<=
opérateur PHP n'est pas total , c'est à dire les deux$a <= $b
et$b <= $a
peut être faux:Pour constituer un ordre partiel strict
<
/>
doit être irréflexif, asymétrique et transitif:L'
<
opérateur PHP est irréfléchi , c'est$a < $a
-à- dire qu'il n'est jamais vrai. Notez que cela n'est vrai qu'à partir de PHP 5.4 . AuparavantINF < INF
évalué àtrue
.L'
<
opérateur PHP n'est pas asymétrique , c'est-à-dire que from$a < $b
ne suit pas!($b < $a)
(Exemple identique à celui de<=
ne pas être anti-symétrique).L'
<
opérateur PHP n'est pas transitif , c'est-à-dire de$a < $b
et$b < $c
ne suit pas$a < $c
:Extra: l'
<
opérateur PHP n'est pas trichotomique , c'est-à-dire tout de$a < $b
,$b < $a
et$a == $b
peut être faux (Exemple identique à celui de<=
ne pas être total).Extra: l'
<
opérateur PHP peut être circulaire , c'est-à-dire qu'il est possible que$a < $b
,$b < $c
et$c < $a
:Remarque: L'exemple ci-dessus lance un avis «L'objet de la classe stdClass n'a pas pu être converti en double».
Vous pouvez trouver quelques bons graphiques pour les opérateurs de comparaison PHP sur PHP Sadness 52 - Opérateurs de comparaison .
En dernière note, je tiens à souligner qu'il ya deux égalités que PHP ne garantie (contrairement à à peu près tout le reste). Ces deux sont toujours valables, simplement parce que le compilateur réduit l'un à l'autre:
la source
($a > $b) and ($b > $c)
avec$a > $c
même si la documentation dit que ces<
/>
opérateurs disent qu'ils sont stricts ?$a == $b
c'est la même chose que(type) $a === (type) $b
. Un exemple simple de ceci est que"15" == "0xf"
, mais(int) "15" !== (int) "0xf"
. Et les règles de comparaison et de casting en PHP sont totalement folles ^^(int)"0xf"
évalue en entier0
, donc bien sûr0 !== 15
. La comparaison dans cet exemple se comporte exactement comme prévu. C'est le casting qui est déroutant ici. J'admets que(INF < INF) === true
c'était un véritable problème de comparaison, mais c'était un cas particulier et il a été résolu comme vous l'avez souligné.Il n'y a pas d' opérateurs de comparaison strictement identiques (
>==
ou<==
) en PHP (par PHP 5.6.14 au moins) , mais il existe plusieurs façons d' imposer une vérification de type stricte avant de vérifier Greater / Lower:if (gettype($a) === gettype($b))
if ((string)$a === (string)$b)
if (($a . '') === ($b . ''))
Prenez note que:
INF
etNAN
sont de typefloat
sousieee754e
est toujours de typefloat
, et jamaisinteger
même si le nombre est petitPHP_INT_MAX
sont automatiquement convertis enfloat
INF
valeurNULL
0
sont convertis d'octal en décimal (par convention)0
en entier supprime le début0
Liste de quelques comparaisons exotiques:
Égal mais pas identique:
Plus bas et plus grand en même temps?
Égal ET identique:
Inférieur ou supérieur:
$a > $b > $c
Énigme quand:$a
n'est pas supérieur à$c
.Comparaison de cordes amusante: 'Queen'
>
'King'>
'Jack'>
'Ace'Consultez également les tableaux de comparaison des types PHP couvrant les paires:
isset()
etis_null()
if()
etempty()
==
vs.===
Vérifiez les différences entre les versions de PHP en direct sur. http://3v4l.org/MAfDu .
la source
if ( (string)$a===(string)$b )
mais n'est-ce pas exactement la même chose queif ( (string)$a==(string)$b )
?(string)1==(string)'01'
->bool(true)
et pour le type-jongle(1 . '')=='01'
->bool(true)
pas exactement la même chose que===
lorsque vous auriezbool(false)
sur les deux comptesINFINITY is equal to INFINITY which is mathematically incorrect!
est une déclaration résolument discutable. Notez également que ceNaN
n'est par convention pas supérieur, inférieur ou égal à tout ce qui est dans n'importe quel langage de programmation que je connais.Après avoir corrigé la deuxième partie de votre question, je laisse la réponse à cette partie aux autres. Je veux juste donner la réponse la plus surprenante à la première partie de votre question, c'est-à-dire s'il existe un exemple d' opérateurs
<
et>
qui sont intransitifs. C'est ici.Ce sont tous
true
:Si
<
étaient transitifs ($a < $b
∧$b < $c
⇒$a < $c
), la dernière ligne seraitmais PHP essaie d'être gentil (?!) et d'interpréter les chaînes comme des nombres chaque fois qu'il le peut.
Il s'avère que, en raison de l'intransitivité ci-dessus,
sort()
peut trier les mêmes éléments dans un ordre différent en fonction de leur ordre d'entrée, même s'il n'y a pas deux éléments==
(et qu'aucun élément n'est NAN). Je l'ai souligné dans un commentaire à sort () , dont l'essence est:la source
sort()
table, l'a également choisie pour les implications pratiques lors de la rédaction du billet de blog connexe The Greatest PHP Value . Merci encore pour votre réponse.usort
autant que possible?usort($arr, 'strcmp')
. Cela fonctionne (pour les chaînes, bien sûr), mais il est préférable d'utilisersort($arr, SORT_STRING)
.