ChatGPT解决这个技术问题 Extra ChatGPT

Type-juggling and (strict) greater/lesser-than comparisons in PHP

PHP is famous for its type-juggling. I must admit it puzzles me, and I'm having a hard time to find out basic logical/fundamental things in comparisons.

For example: If $a > $b is true and $b > $c is true, must it mean that $a > $c is always true too?

Following basic logic, I would say yes however I'm that puzzled I do not really trust PHP in this. Maybe someone can provide an example where this is not the case?

Also I'm wondering with the strict lesser-than and strict greater-than operators (as their meaning is described as strictly which I only knew in the past from the equality comparisons) if it makes any difference if left and right operands are swapped with strictly unequal values:

# Precondition:
if ($a === $b) {
    throw new Exception(
       'Both are strictly equal - can not compare strictly for greater or smaller'
    );
}

($a > $b) !== ($b > $a)

For most of all type comparison combinations these greater / lesser comparison operators are not documented, so reading the manual was not really helpful in this case.

I guess you want to correct that line to be ($a > $b) !== ($b < $a) ?
ah, ok, so I misunderstood that. Will have to fix my answer accordingly. Funny all those people writing treatises instead of answers and not reading your question carefully...

C
Community

PHP's comparison operators deviate from the computer-scientific definitions in several ways:

In order to constitute an equivalence relation == has to be reflexive, symmetric and transitive:

PHP's == operator is not reflexive, i.e. $a == $a is not always true: var_dump(NAN == NAN); // bool(false) Note: The fact that any comparison involving NAN is always false is not specific to PHP. It is mandated by the IEEE 754 Standard for Floating-Point Arithmetic (more info).

PHP's == operator is symmetric, i.e. $a == $b and $b == $a are always the same.

PHP's == operator is not transitive, i.e. from $a == $b and $b == $c does not follows $a == $c: var_dump(true == "a"); // bool(true) var_dump("a" == 0); // bool(true) var_dump(true == 0); // bool(false)

In order to constitute a partial order <=/>= has to be reflexive, anti-symmetric and transitive:

PHP's <= operator is not reflexive, i.e. $a <= $a is not always true (Example same as for ==).

PHP's <= operator is not anti-symmetric, i.e. from $a <= $b and $b <= $a does not follow $a == $b: var_dump(NAN <= "foo"); // bool(true) var_dump("foo" <= NAN); // bool(true) var_dump(NAN == "foo"); // bool(false)

PHP's <= operator is not transitive, i.e. from $a <= $b and $b <= $c does not follow $a <= $c (Example same as for ==).

Extra: PHP's <= operator is not total, i.e. both $a <= $b and $b <= $a can be false: var_dump(new stdClass <= new DateTime); // bool(false) var_dump(new DateTime <= new stdClass); // bool(false)

In order to constitute a strict partial order </> has to be irreflexive, asymmetric and transitive:

PHP's < operator is irreflexive, i.e. $a < $a is never true. Note that this is true only as of PHP 5.4. Previously INF < INF evaluated to true.

PHP's < operator is not asymmetric, i.e. from $a < $b does not follow !($b < $a) (Example same as for <= not being anti-symmetric).

PHP's < operator is not transitive, i.e. from $a < $b and $b < $c does not follow $a < $c: var_dump(-INF < 0); // bool(true) var_dump(0 < TRUE); // bool(true) var_dump(-INF < TRUE); // bool(false)

Extra: PHP's < operator is not trichotomous, i.e. all of $a < $b, $b < $a and $a == $b can be false (Example same as for <= not being total).

Extra: PHP's < operator can be circular, i.e. it is possible that $a < $b, $b < $c and $c < $a: var_dump(INF < []); // bool(true) var_dump([] < new stdClass); // bool(true) var_dump(new stdClass < INF); // bool(true) Note: The above example throws a "Object of class stdClass could not be converted to double" notice.

You can find a few nice graphs for PHP's comparison operators on PHP Sadness 52 - Comparison operators.

As a last note, I want to point out that there are two equalities that PHP does guarantee (unlike pretty much everything else). These two always hold, simply because the compiler reduces one to the other:

($a > $b) == ($b < $a)
($a >= $b) == ($b <= $a)

Wow, nice anwer. So it's not possible to formulate logical expressions with PHP like ($a > $b) and ($b > $c) with $a > $c even though the documentation says those < / > operators say they are strict?
IMHO operators do follow math rules, but only when dealing with the same data types. Type casting is what really creates the confusion here (and in many other situations). When comparing numbers and strings and special values type conversions are done before the operators, so strictly speaking comparison operators are not confusing, casting is...
@ivanhoe011 The truth is: Both are :) PHP's comparison rules and PHP's casting rules differ, you can't simply say that $a == $b is the same as (type) $a === (type) $b. A simple example of this is that "15" == "0xf", but (int) "15" !== (int) "0xf". And both comparison and casting rules in PHP are totally crazy ^^
@NikiC: (int)"0xf" evaluates to integer 0, so of course 0 !== 15. Comparison in this example behaves exactly as expected. It's the casting that's confusing here. I'll admit, (INF < INF) === true was a genuine comparison problem, but it was a special case, and it's been resolved as you pointed out. Great answer.. +1
I don't necessarily fault the designers of PHP for some of the decisions that made sense about type coercion at the time... but I feel like the should have noticed the results of these design choices and immediately realizing the choices were obviously wrong. The most obvious example being @ravz's comment.
P
Peter Mortensen

There are no strict identical comparison operators (>== or <==) in PHP (by PHP 5.6.14 at least), but there are a few ways to enforce a strict type check before checking Greater/Lower:

Check both variable types with if (gettype($a) === gettype($b)) Force your needed type-cast eg. if ((string)$a === (string)$b) Force your needed type-juggle eg. if (($a . '') === ($b . ''))

Take note that:

Floating point precision is limited

INF and NAN are of type float under ieee754

Some Infinity equals some other Infinity (since PHP 5.4)

Scientific notation e is always of type float, and never integer even if the number is small

Integers going over PHP_INT_MAX get automatically converted to float

Floats over system's boundaries get the INF value

Undefined variables are of type and value NULL

Integers preceded by 0 are converted from octal to decimal (by convention)

Converting Strings containing an integer with a leading 0 to integer strips the leading 0

List of some exotic comparisons:

Very strange:
     $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

Equal but not identical:

$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   false
  float(NAN)     bool(true)     false   false    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   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

Lower and Greater at the same time?

$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

Equal AND identical:

$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

Lower or Greater:

$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 Conundrum when: $a is not greater than $c.

A&ltC   : float(NAN)  >  str('a')   >   str('')
A&ltC   : float(NAN)  >  str('a')   >   str('1')
A&ltC   : float(NAN)  >  str('a')   >   str('A')
A&ltC   : float(NAN)  >  str('a')   >   str('0')
A&ltC   : float(NAN)  >  str('1')   >   str('')
A&ltC   : float(NAN)  >  str('1')   >   str('0')
A&ltC   : float(NAN)  >  str('A')   >   str('')
A&ltC   : float(NAN)  >  str('A')   >   str('1')
A&ltC   : float(NAN)  >  str('A')   >   str('0')
A&ltC   : float(NAN)  >  str('0')   >   str('')
A&ltC   :   str('')   > float(NAN)  >   str('a')
A&ltC   :   str('')   > float(NAN)  >   str('1')
A&ltC   :   str('')   > float(NAN)  >   str('A')
A&ltC   :   str('')   > float(NAN)  >   str('0')
A&ltC   :  str('a')   >   str('')   >  float(NAN)
A&ltC   :  str('a')   >  str('1')   >  float(NAN)
A&ltC   :  str('a')   >  str('A')   >  float(NAN)
A&ltC   :  str('a')   >  str('0')   >  float(NAN)
A&ltC   :  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(true)  >  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  :   array()   >  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')

Fun string comparison: 'Queen' > 'King' > 'Jack' > 'Ace'

Also check out PHP type comparison tables covering pairs:

isset() and is_null()

if() and empty()

boolean == vs. ===

Check the differences between PHP versions live at. http://3v4l.org/MAfDu.


+1 let alone the scrollable "tables" with the fixed-column headers - nifty idea ;)
Does one need to use strict operator when type-casting? I mean you've written if ( (string)$a===(string)$b ) but isn't this exactly the same as if ( (string)$a==(string)$b )?
@Voitcus yes for both type-cast (string)1==(string)'01' -> bool(true) and for type-juggle (1 . '')=='01' -> bool(true) not exactly the same as === when you would get bool(false) on both accounts
One nit-pick: octal values are not "converted on assignment", they are interpreted by the compiler, which has to turn ASCII into actual binary numbers.
INFINITY is equal to INFINITY which is mathematically incorrect! is a decidedly debatable statement. Also note that NaN is by convention not greater than, less than or equal to anything in any programming language that I know of.
W
Walter Tross

After your correction of the second part of your question, I leave the answer to that part to the others. I just want to give the most surprising answer to the first part of your question, i.e., whether there is an example of the < and > operators being intransitive. Here it is.

These are all true:

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

If < were transitive ($a < $b$b < $c$a < $c), the last line would be

"10" < "2"

but PHP tries to be kind (?!) and interpret strings as numbers whenever it can.

It turns out that, because of the above intransitivity, sort() can sort the same elements into a different order depending on their input order, even when no two elements are == (and no element is NAN). I pointed this out in a comment to sort(), the essence of which is:

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" )

the previous comment refers to a part of the answer (related to the second part of the question) that I have deleted in the meanwhile
Removed that now ;) And nice new sort() table, picked it as well for the practical implications when writing the related blog post The Greatest PHP Value. Thanks again for your answer.
Does it mean that one should use usort whenever possible?
@Voitcus: I guess you mean usort($arr, 'strcmp'). This works (for strings, of course), but it's best to use sort($arr, SORT_STRING).
@WalterTross I mean always use your own function (not only for strings) to ensure it is always correct