Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
523 views
in Technique[技术] by (71.8m points)

if statement - 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...