PHPは、型ジャグリングで有名です。私はそれが私を困惑させていることを認めなければなりません。
例:$a > $b
は真であり、$b > $c
はtrueです。つまり、$a > $c
はalwaystrueでもありますか?
基本的な論理に従って、yesと言いますが、私は本当にこれを信用していないことに困惑しています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の==
演算子は not reflexive です。つまり、$a == $a
は常に真ではありません。
var_dump(NAN == NAN); // bool(false)
注:NAN
を含む比較は常にfalse
であるという事実は、PHPに固有のものではありません。 IEEE 754浮動小数点演算の標準で義務付けられています( 詳細 )。
PHPの==
演算子は symmetric です。つまり、$a == $b
と$b == $a
は常に同じです。
PHPの==
演算子は not推移的です。つまり、$a == $b
と$b == $c
からは not は$a == $c
の後に続きます。
var_dump(true == "a"); // bool(true)
var_dump("a" == 0); // bool(true)
var_dump(true == 0); // bool(false)
部分順序<=
/>=
を構成するには、再帰的、反対称的、推移的でなければなりません。
PHPの<=
演算子は not reflexive です。つまり、$a <= $a
は常に真とは限りません(例は==
と同じです)。
PHPの<=
演算子は反対称ではありません。つまり、$a <= $b
からであり、$b <= $a
は$a == $b
の後に続きません。
var_dump(NAN <= "foo"); // bool(true)
var_dump("foo" <= NAN); // bool(true)
var_dump(NAN == "foo"); // bool(false)
PHPの<=
演算子は not推移的ではありません。つまり、$a <= $b
からであり、$b <= $c
は$a <= $c
の後に続きません(例は==
と同じです)。
Extra:PHPの<=
演算子は not total です。つまり、$a <= $b
と$b <= $a
の両方がfalseになる可能性があります。
var_dump(new stdClass <= new DateTime); // bool(false)
var_dump(new DateTime <= new stdClass); // bool(false)
厳密な半順序<
/>
を構成するには、非再帰的、非対称的、推移的でなければなりません。
PHPの<
演算子は irreflexive です。つまり、$a < $a
は決して真ではありません。これは真であることに注意してください PHP 5.4 )のみ。以前はINF < INF
はtrue
に評価されていました。
PHPの<
演算子は not asymmetric です。つまり、$a < $b
は!($b < $a)
の後に続きません(反対称でない<=
の例と同じです)。
PHPの<
演算子は推移的ではありません。つまり、$a < $b
からであり、$b < $c
は$a < $c
の後に続きません。
var_dump(-INF < 0); // bool(true)
var_dump(0 < TRUE); // bool(true)
var_dump(-INF < TRUE); // bool(false)
Extra:PHPの<
演算子は not trichotomous です。つまり、$a < $b
、$b < $a
、および$a == $b
のすべてがfalseになる可能性があります(例:<=
は合計ではありません)。
Extra:PHPの<
演算子は circular にできます。つまり、$a < $b
、$b < $c
、および$c < $a
が可能です。
var_dump(INF < []); // bool(true)
var_dump([] < new stdClass); // bool(true)
var_dump(new stdClass < INF); // bool(true)
注:上記の例は、「クラスstdClassのオブジェクトをdoubleに変換できませんでした」という通知をスローします。
PHP Sadness 52-比較演算子 にPHPの比較演算子のいくつかの素敵なグラフがあります。
最後の注意として、私はPHP doesを保証する2つの平等があります(他のほとんどすべてとは異なります)。これら2つは常に成り立ちます。コンパイラは、一方を他方に減らします。
($a > $b) == ($b < $a)
($a >= $b) == ($b <= $a)
質問の2番目の部分を修正した後、その部分に対する答えを他の人に任せます。私はあなたの質問の最初の部分、つまり_<
_および_>
_演算子が非推移的である例があるかどうかに最も驚くべき答えをしたいだけです。ここにあります。
これらはすべてtrue
です:
_"10" < "1a"
"1a" < "2"
"10" > "2"
_
_<
_が推移的であった場合(_$a < $b
_∧_$b < $c
_⇒_$a < $c
_)、最後の行は
_"10" < "2"
_
しかしPHPは親切(?!)になろうとし、可能な限り文字列を数字として解釈します。
上記の非推移性のため、sort()
は入力順序に応じてsame要素をdifferent順序にソートできることがわかります2つの要素が_==
_でない場合(および要素がNANでない場合)。これを sort()へのコメント で指摘しました。その本質は次のとおりです。
_sort(array("10", "1a", "2" )) => array("10", "1a", "2" )
sort(array("10", "2", "1a")) => array("1a", "2", "10")
sort(array("1a", "10", "2" )) => array("2", "10", "1a")
sort(array("1a", "2", "10")) => array("1a", "2", "10")
sort(array("2", "10", "1a")) => array("2", "10", "1a")
sort(array("2", "1a", "10")) => array("10", "1a", "2" )
_