118

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)

すべての型比較の組み合わせのほとんどについて、これらの大/小比較演算子は文書化されていないため、この場合、マニュアルを読んでもあまり役に立ちませんでした。

4

3 に答える 3

210

PHP の比較演算子は、いくつかの点でコンピューター科学の定義から逸脱しています。

等価関係 を構成するに==は、再帰的、対称的、および推移的でなければなりません。

  • PHP の==演算子はreflexiveではありません。つまり、$a == $a常に真であるとは限りません。

    var_dump(NAN == NAN); // bool(false)
    

    NAN注:常に含まれる比較はfalse、PHP に固有のものではありません。これは、浮動小数点演算に関する IEEE 754 標準 (詳細) によって義務付けられています。

  • PHP の==演算子は対称的です。つまり$a == $b、 and$b == $aは常に同じです。

  • PHP の==演算子は推移的ではありません。つまり、 from$a == $bおよび$b == $cdoes not follow$a == $cです。

    var_dump(true == "a"); // bool(true)
    var_dump("a" == 0);    // bool(true)
    var_dump(true == 0);   // bool(false)
    

半順序 を構成するには、<=/>=が再帰的、反対称的、および推移的でなければなりません。

  • PHP の<=演算子はreflexiveではありません。つまり、$a <= $a常に true であるとは限りません (例は for と同じ==)。

  • PHP の<=演算子は反対称ではありません。つまり、from $a <= $band $b <= $adoes not follow$a == $bです。

    var_dump(NAN <= "foo"); // bool(true)
    var_dump("foo" <= NAN); // bool(true)
    var_dump(NAN == "foo"); // bool(false)
    
  • PHP の<=演算子は推移的ではありません。つまり、from $a <= $band$b <= $cは続きません$a <= $c(for と同じ例==)。

  • 補足: PHP の<=演算子はtotalではありません。つまり、 both $a <= $band$b <= $aは false になる可能性があります。

    var_dump(new stdClass <= new DateTime); // bool(false)
    var_dump(new DateTime <= new stdClass); // bool(false)
    

厳密な半順序 を構成するためには、</>は非反射的、非対称的、推移的でなければなりません:

  • PHP の<演算子は非反射的です。つまり、$a < $a真になることはありません。これはPHP 5.4 の時点でのみ当てはまることに注意してください。以前INF < INFは に評価されましたtrue

  • PHP の<演算子は非対称ではありません。つまり、from$a < $bは続きません(反対称!($b < $a)でない場合と同じ例)。<=

  • PHP の<演算子は推移的ではありません。つまり、 from$a < $bおよび$b < $cdoes not follow$a < $cです。

    var_dump(-INF < 0);    // bool(true)
    var_dump(0 < TRUE);    // bool(true)
    var_dump(-INF < TRUE); // bool(false)
    
  • おまけ: PHP の演算子 <は3 分法ではありません。$a < $b$b < $a$a == $b<=

  • おまけ: PHP の<演算子は循環することができます。つまり$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が保証する2 つの同等性があることを指摘したいと思います(ほとんどすべてのものとは異なります)。これら 2 つは、単にコンパイラが一方を他方に還元するため、常に成立します。

($a > $b) == ($b < $a)
($a >= $b) == ($b <= $a)
于 2013-04-04T14:10:28.867 に答える
91

PHP には(少なくとも PHP 5.6.14 までは)厳密な同一比較演算子 (または)はありません が、大きい/小さいをチェックする前に厳密な型チェックを強制する方法がいくつかあります。>==<==

  1. 両方の変数タイプを確認してくださいif (gettype($a) === gettype($b))
  2. 必要な型キャストを強制します。if ((string)$a === (string)$b)
  3. 必要なタイプジャグルを強制します。if (($a . '') === ($b . ''))

次の点に注意してください。

  • 浮動小数点の精度には制限があります
  • INFおよびの下NANのタイプですfloat
  • 一部の無限大は他の一部の無限大に等しい(PHP 5.4 以降)
  • 科学表記法eは常に 型であり、数値が小さくてもfloat決して型ではないinteger
  • 超える整数PHP_INT_MAXは自動的に変換されますfloat
  • システムの境界を超えるフロートはINF値を取得します
  • 未定義の変数の型と値NULL
  • が前に付いている整数は0、8 進数から 10 進数に変換されます (慣例により)
  • 0 先頭が整数の整数を含む文字列を整数に変換すると、先頭が取り除かれます0

いくつかのエキゾチックな比較のリスト:

非常に奇妙な:
     $a VS. $b $a>$b $a<$b $a<=$b $a>=$b $a==$b $a===$b
  float(NAN) float(-INF) false false false false false false
  float(NAN) float(0) false false false false false false
  float(NAN) float(1) false false false false false false
  float(NAN) float(INF) false false false false false false
  float(NAN) float(NAN) false false false false false false
  float(NAN) int(-1) false false false false false false
  float(NAN) int(0) false false false false false false
  float(NAN) int(1) false false false false false false

等しいが同一ではない:

     $a VS. $b $a>$b $a<$b $a<=$b $a>=$b $a==$b $a===$b
  NULL(NULL) array() false false true true true false
  NULL(NULL) bool(false) false false true true true false
  NULL(NULL) float(0) false false true true true false
  NULL(NULL) int(0) false false true true true false
  NULL(NULL) str('') false false true true true false
   array() bool(false) false false true true true false
 bool(false) float(0) false false true true true false
 bool(false) int(0) false false true true true false
   str('') bool(false) false false true true true false
 bool(false) str('0') false false true true true false
 float(-INF) bool(true) false false true true true false
  bool(true) float(1) false false true true true false
  float(INF) bool(true) false false true true true true false
  float(NAN) bool(true) false false true true true true false
  bool(true) int(-1) false false true true true false
  bool(true) int(1) false false true true true false
  bool(true) str("\0") false false true true true false
  bool(true) str('+') false false true true true false
  bool(true) str('-') false false true true true false
  bool(true) str('01') false false true true true false
  bool(true) str('1') false false true true true false
  bool(true) str('false') false false true true true false
 str('text') bool(true) false false true true true false
 str('true') bool(true) false false true true true false
    int(0) float(0) false false true true true false
  str("\0") float(0) false false true true true false
   str('') float(0) false false true true true false
   str('+') float(0) false false true true true false
   str('-') float(0) false false true true true false
   str('0') float(0) false false true true true false
 str('false') float(0) false false true true true false
 str('text') float(0) false false true true true false
 str('true') float(0) false false true true true false
    int(1) float(1) false false true true true true false
   float(1) str('01') false false true true true false
   float(1) str('1') false false true true true false
  str("\0") int(0) false false true true true false
   str('') int(0) false false true true true false
   str('+') int(0) false false true true true false
   str('-') int(0) false false true true true false
    int(0) str('0') false false true true true false
 str('false') int(0) false false true true true false
 str('text') int(0) false false true true true false
 str('true') int(0) false false true true true false
    int(1) str('01') false false true true true false
    int(1) str('1') false false true true true false
   str('1') str('01') false false true true true false

ローワーとグレーターを同時に?

     $a VS. $b $a>$b $a<$b $a<=$b $a>=$b $a==$b $a===$b
  float(NAN) str("\0") true true true true false false
  float(NAN) str('') true true true true false false
  float(NAN) str('+') true true true true false false
  float(NAN) str('-') true true true true false false
  float(NAN) str('0') true true true true false false
  float(NAN) str('01') true true true true false false
  float(NAN) str('1') true true true true false false
  float(NAN) str('false') true true true true false false
  float(NAN) str('text') true true true true false false
  float(NAN) str('true') true true true true false false

等しい AND 同一:

     $a VS. $b $a>$b $a<$b $a<=$b $a>=$b $a==$b $a===$b
  NULL(NULL) NULL(NULL) false false true true true true
 float(-INF) float(-INF) false false true true true true
  float(INF) float(INF) false false true true true true

低いか高い:

     $a VS. $b $a>$b $a<$b $a<=$b $a>=$b $a==$b $a===$b
  NULL(NULL) bool(true) false true true false false false
 float(-INF) NULL(NULL) true false false true false false
  NULL(NULL) float(1) false true true false false false
  float(INF) NULL(NULL) true false false true false false
  float(NAN) NULL(NULL) true false false true false false
  NULL(NULL) int(-1) false true true false false false
  NULL(NULL) int(1) false true true false false false
  NULL(NULL) str("\0") false true true false false false
  NULL(NULL) str('+') false true true false false false
  NULL(NULL) str('-') false true true false false false
  NULL(NULL) str('0') false true true false false false
  NULL(NULL) str('01') false true true false false false
  NULL(NULL) str('1') false true true false false false
  NULL(NULL) str('false') false true true false false false
  NULL(NULL) str('text') false true true false false false
  NULL(NULL) str('true') false true true false false false
   array() bool(true) false true true false false false
 float(-INF) array() false true true false false false
   array() float(0) true false false true false false
   array() float(1) true false false true false false
  float(INF) array() false true true false false false
  float(NAN) array() false true true false false false
   array() int(-1) true false false true false false
   array() int(0) true false false true false false
   array() int(1) true false false true false false
   array() str("\0") true false false true false false
   str('') array() false true true false false false
   array() str('+') true false false true false false
   array() str('-') true false false true false false
   array() str('0') true false false true false false
   array() str('01') true false false true false false
   array() str('1') true false false true false false
   array() str('false') true false false true false false
   array() str('text') true false false true false false
   array() str('true') true false false true false false
  bool(true) bool(false) true false false true false false
 float(-INF) bool(false) true false false true false false
   float(1) bool(false) true false false true false false
  float(INF) bool(false) true false false true false false
  float(NAN) bool(false) true false false true false false
 bool(false) int(-1) false true true false false false
    int(1) bool(false) true false false true false false
 bool(false) str("\0") false true true false false false
 bool(false) str('+') false true true false false false
 bool(false) str('-') false true true false false false
 bool(false) str('01') false true true false false false
   str('1') bool(false) true false false true false false
 bool(false) str('false') false true true false false false
 str('text') bool(false) true false false true false false
 str('true') bool(false) true false false true false false
  bool(true) float(0) true false false true false false
  bool(true) int(0) true false false true false false
   str('') bool(true) false true true false false false
  bool(true) str('0') true false false true false false
 float(-INF) float(0) false true true false false false
 float(-INF) float(1) false true true false false false
  float(INF) float(-INF) true false false true false false
 float(-INF) int(-1) false true true false false false
 float(-INF) int(0) false true true false false false
 float(-INF) int(1) false true true false false false
 float(-INF) str("\0") false true true false false false
 float(-INF) str('') false true true false false false
 float(-INF) str('+') false true true false false false
 float(-INF) str('-') false true true false false false
 float(-INF) str('0') false true true false false false
 float(-INF) str('01') false true true false false false
 float(-INF) str('1') false true true false false false
 float(-INF) str('false') false true true false false false
 float(-INF) str('text') false true true false false false
 float(-INF) str('true') false true true false false false
   float(1) float(0) true false false true false false
  float(INF) float(0) true false false true false false
   float(0) int(-1) true false false true false false
    int(1) float(0) true false false true false false
   float(0) str('01') false true true false false false
   str('1') float(0) true false false true false false
  float(INF) float(1) true false false true false false
   float(1) int(-1) true false false true false false
   float(1) int(0) true false false true false false
   float(1) str("\0") true false false true false false
   str('') float(1) false true true false false false
   float(1) str('+') true false false true false false
   float(1) str('-') true false false true false false
   float(1) str('0') true false false true false false
   float(1) str('false') true false false true false false
 str('text') float(1) false true true false false false
 str('true') float(1) false true true false false false
  float(INF) int(-1) true false false true false false
  float(INF) int(0) true false false true false false
  float(INF) int(1) true false false true false false
  float(INF) str("\0") true false false true false false
  float(INF) str('') true false false true false false
  float(INF) str('+') true false false true false false
  float(INF) str('-') true false false true false false
  float(INF) str('0') true false false true false false
  float(INF) str('01') true false false true false false
  float(INF) str('1') true false false true false false
  float(INF) str('false') true false false true false false
  float(INF) str('text') true false false true false false
  float(INF) str('true') true false false true false false
    int(0) int(-1) true false false true false false
    int(1) int(-1) true false false true false false
  str("\0") int(-1) true false false true false false
   str('') int(-1) true false false true false false
   str('+') int(-1) true false false true false false
   str('-') int(-1) true false false true false false
   str('0') int(-1) true false false true false false
   int(-1) str('01') false true true false false false
   str('1') int(-1) true false false true false false
 str('false') int(-1) true false false true false false
 str('text') int(-1) true false false true false false
 str('true') int(-1) true false false true false false
    int(1) int(0) true false false true false false
    int(0) str('01') false true true false false false
   str('1') int(0) true false false true false false
    int(1) str("\0") true false false true false false
   str('') int(1) false true true false false false
    int(1) str('+') true false false true false false
    int(1) str('-') true false false true false false
    int(1) str('0') true false false true false false
    int(1) str('false') true false false true false false
str('text') int(1) false true true false false false
 str('true') int(1) false true true false false false
   str('') str("\0") false true true false false false
   str('+') str("\0") true false false true false false
   str('-') str("\0") true false false true false false
  str("\0") str('0') false true true false false false
  str("\0") str('01') false true true false false false
   str('1') str("\0") true false false true false false
 str('false') str("\0") true false false true false false
 str('text') str("\0") true false false true false false
 str('true') str("\0") true false false true false false
   str('') str('+') false true true false false false
   str('') str('-') false true true false false false
   str('') str('0') false true true false false false
   str('') str('01') false true true false false false
   str('') str('1') false true true false false false
   str('') str('false') false true true false false false
   str('') str('text') false true true false false false
   str('') str('true') false true true false false false
   str('-') str('+') true false false true false false
   str('+') str('0') false true true false false false
   str('+') str('01') false true true false false false
   str('1') str('+') true false false true false false
 str('false') str('+') true false false true false false
 str('text') str('+') true false false true false false
 str('true') str('+') true false false true false false
   str('-') str('0') false true true false false false
   str('-') str('01') false true true false false false
   str('1') str('-') true false false true false false
 str('false') str('-') true false false true false false
 str('text') str('-') true false false true false false
 str('true') str('-') true false false true false false
   str('0') str('01') false true true false false false
   str('1') str('0') true false false true false false
 str('false') str('0') true false false true false false
 str('text') str('0') true false false true false false
 str('true') str('0') true false false true false false
 str('false') str('01') true false false true false false
 str('text') str('01') true false false true false false
 str('true') str('01') true false false true false false
   str('1') str('false') false true true false false false
 str('text') str('1') true false false true false false
 str('true') str('1') true false false true false false
str('text') str('false') true false false true false false
 str('true') str('false') true false false true false false
str('true') str('text') true false false true false false

$a > $b > $c次の場合の難問:$aが より大きくない$c

A<C : float(NAN) > str('a') > str('')
A<C : float(NAN) > str('a') > str('1')
A<C : float(NAN) > str('a') > str('A')
A<C : float(NAN) > str('a') > str('0')
A<C : float(NAN) > str('1') > str('')
A<C : float(NAN) > str('1') > str('0')
A<C : float(NAN) > str('A') > str('')
A<C : float(NAN) > str('A') > str('1')
A<C : float(NAN) > str('A') > str('0')
A<C : float(NAN) > str('0') > str('')
A<C : str('') > float(NAN) > str('a')
A<C : str('') > float(NAN) > str('1')
A<C : str('') > float(NAN) > str('A')
A<C : str('') > float(NAN) > str('0')
A<C : str('a') > str('') > float(NAN)
A<C : str('a') > str('1') > float(NAN)
A<C : str('a') > str('A') > float(NAN)
A<C : str('a') > str('0') > float(NAN)
A<C : str('0') > str('') > float(NAN)
A==C : bool(true) > str('') > float(NAN)
A==C : bool(true) > str('') > float(-INF)
A==C : bool(true) > str('') > int(-1)
A==C : bool(true) > str('') > float(-1)
A==C : bool(true) > array() > float(NAN)
A==C : bool(true) > array() > float(INF)
A==C : bool(true) > array() > float(-INF)
A==C : bool(true) > array() > str('a')
A==C : bool(true) > array() > int(1)
A==C : bool(true) > array() > float(1)
A==C : bool(true) > array() > str('1')
A==C : bool(true) > array() > str('A')
A==C : bool(true) > array() > int(-1)
A==C : bool(true) > array() > float(-1)
A==C : bool(true) > int(0) > float(-INF)
A==C : bool(true) > int(0) > int(-1)
A==C : bool(true) > int(0) > float(-1)
A==C : bool(真) > str('0') > float(NAN)
A==C : bool(true) > str('0') > float(-INF)
A==C : bool(true) > str('0') > int(-1)
A==C : bool(true) > str('0') > float(-1)
A==C : bool(true) > float(0) > float(-INF)
A==C : bool(true) > float(0) > int(-1)
A==C : bool(true) > float(0) > float(-1)
A==C : int(1) > str('a') > str('1')
A==C : int(1) > str('A') > str('1')
A==C : float(1) > str('a') > str('1')
A==C : float(1) > str('A') > str('1')
A==C : str('a') > str('1') > int(0)
A==C : str('a') > str('1') > float(0)
A==C : str('') > float(-INF) > NULL(NULL)
A==C : str('') > float(-INF) > bool(false)
A==C : str('') > int(-1) > NULL(NULL)
A==C : str('') > int(-1) > bool(false)
A==C : str('') > float(-1) > NULL(NULL)
A==C : str('') > float(-1) > bool(false)
A==C : array() > float(NAN) > NULL(NULL)
A==C : array() > float(NAN) > bool(false)
A==C : array() > float(INF) > NULL(NULL)
A==C : array() > float(INF) > bool(false)
A==C : array() > float(-INF) > NULL(NULL)
A==C : array() > float(-INF) > bool(false)
A==C : array() > str('a') > NULL(NULL)
A==C : array() > str('a') > bool(false)
A==C : array() > int(1) > NULL(NULL)
A==C : array() > int(1) > bool(false)
A==C : array() > float(1) > NULL(NULL)
A==C : array() > float(1) > bool(false)
A==C : array() > str('1') > NULL(NULL)
A==C : array() > str('1') > bool(false)
A==C : array() > str('A') > NULL(NULL)
A==C : array() > str('A') > bool(false)
A==C : 配列() > str('0') > NULL(NULL)
A==C : array() > int(-1) > NULL(NULL)
A==C : array() > int(-1) > bool(false)
A==C : array() > float(-1) > NULL(NULL)
A==C : array() > float(-1) > bool(false)
A==C : str('') > float(NAN) > bool(false)
A==C : str('') > float(NAN) > NULL(NULL)
A==C : str('A') > str('1') > int(0)
A==C : str('A') > str('1') > float(0)
A==C : int(0) > float(-INF) > NULL(NULL)
A==C : int(0) > float(-INF) > bool(false)
A==C : int(0) > int(-1) > NULL(NULL)
A==C : int(0) > int(-1) > bool(false)
A==C : int(0) > float(-1) > NULL(NULL)
A==C : int(0) > float(-1) > bool(false)
A==C : str('0') > float(NAN) > bool(false)
A==C : str('0') > float(-INF) > bool(false)
A==C : str('0') > int(-1) > bool(false)
A==C : str('0') > float(-1) > bool(false)
A==C : float(0) > float(-INF) > NULL(NULL)
A==C : float(0) > float(-INF) > bool(false)
A==C : float(0) > int(-1) > NULL(NULL)
A==C : float(0) > int(-1) > bool(false)
A==C : float(0) > float(-1) > NULL(NULL)
A==C : float(0) > float(-1) > bool(false)
A===C : str('0') > float(NAN) > str('0')
A===C : str('') > float(NAN) > str('')
A===C : str('a') > float(NAN) > str('a')
A===C : str('1') > float(NAN) > str('1')
A===C : str('A') > float(NAN) > str('A')

楽しい文字列比較: 'Queen' >'King' >'Jack' >'Ace'

ペアをカバーするPHP 型比較表もチェックしてください。

  • isset()is_null()
  • if()empty()
  • ブール値==vs.===

にある PHP バージョン間の違いを確認してください。http://3v4l.org/MAfDu

于 2013-04-04T19:48:07.563 に答える
23

質問の 2 番目の部分を修正した後、その部分への回答は他の人に任せます。<あなたの質問の最初の部分、つまりand>演算子が自動詞である例があるかどうかについて、最も驚くべき答えを出したいだけです。ここにあります。

これらはすべてtrue:

"10" < "1a"
"1a" < "2"
"10" > "2"

<推移的 ( $a < $b$b < $c⇒ ) の場合$a < $c、最後の行は次のようになります。

"10" < "2"

しかし、PHP は親切 (?!) であり、可能な限り文字列を数値として解釈しようとします。

上記の非推移性により、同じ要素を入力順序に応じて異なるsort()順序に並べ替えることができることがわかります。これは、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" )
于 2013-04-06T22:29:52.450 に答える