Comparison operators

Comparison operators such as <, >, and == return either a 1 or a 0 (or nothing) depending on whether the comparison was true or false, and it is this value that PHP uses to decide actions. Consider this following piece of PHP code:

<?php
    
if ($foo < 10) {
        
// do stuff
    
}
?>

The less-than operator, <, will compare $foo to 10, and if it is less than (but not equal to) ten then < will return a 1. This will make the line read "if (1) {". As mentioned already, PHP considers 0 or nothing to be false, and anything else to be true, which means that the line reads as "if (true) {". Naturally "true" is always true, so the true block of the if statement will execute.

Now that you know how it works, you should be able to avoid a common mistake with range checking. Consider this next script:

<?php
    
if ($a <= $b <= $c) {
        
// do stuff
    
}
?>

Here we appear to be checking that $b must be greater or equal to $a and less than or equal to $c. However, what actually happens is quite different! First, PHP compares $a with $b, and if $a is less than or equal to $b then the condition is 1, "true". However, we then find that PHP is comparing 1 against $c to see whether it is equal to or lower than it, as opposed to comparing $b against $c. This is almost certainly not what the script writer intended - the code needs to be rewritten like this:

<?php
    
if ($a <= $b && $b <= $c) {
        
// do stuff
    
}
?>

In the modified version the two checks are kept separate, which is much better.

Now, I'm going to insult you: do you know what the equality operator, ==, does? If your answer is "gosh, Paul, it returns true if two values are the same", then you're in the majority.

Consider this script:

if (31415926535897932 == 31415926535897933) {
    echo
"Numbers are the same!\n";
} else {
    echo
"Numbers are not the same!\n";
}

Don't worry about spending any time comparing the two numbers: the first is Pi to 17 places and the second is Pi to 17 places + 1. Both have their decimal places removed. I want you to have a think about what that script will output. Here's a hint: it's a trick question!

Before reading the answer, I strongly suggest you try it out in PHP, because it will hopefully make my job explaining it a little easier.

What will happen is that PHP will output "Numbers are the same!" despite them clearly different. The reason for this is because PHP does not work well with such large numbers as these, and, past a certain point, is unable to compare numbers using a straight equality operator.

Internally, PHP uses an "integer" type for most numbers. However, these only go so far: if you add a large integer to a large integer, PHP will see that the result is too big to fit into a normal integer and will assign it to a floating-point number. Floating-point numbers (floats) themselves only go so high, however, and there's a point around the sixteen-digit mark where PHP will just lose the plot entirely.

This script illustrates the point neatly:

$foo =  2147483647;
    var_dump($foo);

    ++$foo;
    var_dump($foo);

    $bar = 31415926535897932;
    $baz = 31415926535897933;
    var_dump($bar);
    var_dump($baz);

Here's the output that will generate:

int(2147483647)
float(2147483648)
float(31415926535898000)
float(31415926535898000)

So, the first number is an int (integer), but adding one to it pushes it over the limit of acceptably sized integers, so PHP quietly converts it to a floating-point number (float). Look at the output of the last two numbers, though: both are floats, and, because the default accuracy of floats is 14 decimal places, both get trimmed to 31415926535898. So, when our comparison comes along, it quite rightly finds them to be the same.

There are two solutions to this problem, neither of which are pretty. First, you can compare the two numbers as if they were strings. PHP compares strings letter-by-letter and can compare strings of any size, which makes this a possibility. However, it's not as simple as just putting quotes around big numbers: PHP, being a loosely typed language, will see that the strings contain numbers and automatically convert them to integers, causing the same problem.

The solution here is to use the absolute equality operator, ===, which tests whether two values are the same and of the same type . Thus, if we put quotes around our numbers to make them into strings and compare them using ===, PHP will not automatically convert them to integers because we have asked it to ensure the types are the same. As a result, it will compare the two numbers as strings, which is just what we want. Here's how that looks in code:

if ("31415926535897932" === "31415926535897933") {
    echo
"Numbers are the same!\n";
} else {
    echo
"Numbers are not the same!\n";
}

 

Next chapter: Complete operator list >>

Previous chapter: Shorthand unary operators

Jump to:

 

Home: Table of Contents

Follow us on Identi.ca or Twitter

Username:   Password:
Create Account | About TuxRadar