Key Takeaways
- Floating-point numbers in PHP can lead to surprising results due to the finite precision with which computers represent numbers. For example, the operation ((0.1 + 0.7) * 10) cast as an integer will result in 7, not 8 as expected due to precision issues.
- PHP increments strings in a unique way. If the string ends with a number, using an increment operator will increase the letter following it in the alphabet. However, if the string ends with a non-alphanumeric character, there is no effect.
- The in_array() function in PHP can return unexpected results due to PHP’s loose comparison rules. A non-empty and non-zero-filled string is equal to true and to all non-zero numbers. To avoid this, use the third optional parameter of in_array() to compare values strictly.
- PHP’s handling of data types and comparisons can lead to unexpected behaviors. It’s important to double-check data types before using them in operations and be aware of the problems of loose comparisons and loose data types.
Floating Point Imprecision
Most of you probably know that floating-point numbers cannot really represent all real numbers. Besides, some operations between two well represented numbers can lead to surprising situations. This is because the finite precision with which computers represent numbers and so it affects not just PHP but all the programming languages. Inaccuracies in floating point problems have been given programmers headaches from the beginning of the discipline. About this question many words have been said, but one of the most important articles written is What Every Computer Scientist Should Know About Floating-Point Arithmetic. If you’ve never had a chance to read it, I strongly suggest you do so. Let’s look at this very small snippet:<?php
echo (int) ((0.1 + 0.7) * 10);
What do you think will be the result? If you guessed 8, you’d be wrong… I’m sorry, you lost the prize! This code will actually print 7! For those who have a Zend Certification, this example is already known. Infact, you can find it in Zend PHP 5 Certification Study Guide.
Now let’s see why this happens. The first operation executed is:
0.1 + 0.7 // result is 0.79999999999
The result of the arithmetic expression is stored internally as 0.7999999, not 0.8 due to the precision issue, and this is where the problem starts.
The second operation executed is:
0.79999999 * 10 = 7.999999999
This operation works well but preserves the error.
The third and last operation executed is:
(int) 7.9999999 // result is 7
The expression makes use of an explicit cast. When a value is convert to int
, PHP truncates the decimal portion of the number which makes the result 7.
There are two interesting things to note here:
- If you cast the number to
float
instead ofint
, or if you don’t cast at all, you’ll get 8 as result as you expected. - Although the CPU doesn’t know, and we actually we got this error due to its imprecisions, it’s working accordingly to the mathematics paradox that asserts 0.999… is equal to 1.
Whenever the precision of your calculation is a relevant factor to the proper functioning of your application, you should consider using a (sic) the arbitrary precision functions provided by the BCMath extension (you can search for it in your copy of the PHP manual) instead of PHP’s built-in data types.
How PHP “Increments” Strings
During our everyday work we write instructions that perform incrementing/decrementing operations like these:<?php
$a = 5;
$b = 6;
$a++;
++$b;
Everyone easily understands what’s going on with those statements. But given the following statements, guess what will be the output:
<?php
$a = 1;
$b = 3;
echo $a++ + $b;
echo $a + ++$b;
echo ++$a + $b++;
Did you write down your answers? Good. Let’s check ’em all.
4 6 7Not too difficult, right? Now let’s raise the bar a little. Have you ever tried to increment strings? Try to guess what the output will be for the following:
<?php
$a = 'fact_2';
echo ++$a;
$a = '2nd_fact';
echo ++$a;
$a = 'a_fact';
echo ++$a;
$a = 'a_fact?';
echo ++$a;
It’s not so easy this time, is it. Let’s uncover the answers.
fact_3 2nd_facu a_facu a_fact?Surprised? Using an increment operator on a string that ends with a number has the effect of increasing the letter (the one following it in the alphabet, e.g. t -> u). Regardless if the string starts with digits or not, the last character is changed. But there is no effect if the string ends with a non-alphanumeric character. This is well documented by the official documentation about the incrementing/decrementing operators but most of you may not have read it because you probably thought nothing special was there. I must admit I thought the same until a short time ago.
PHP follows Perl’s convention when dealing with arithmetic operations on character variables and not C’s. For example, in PHP and Perl $a = ‘Z’; $a++; turns $a into ‘AA’, while in C a = ‘Z’; a++; turns a into ‘[‘ (ASCII value of ‘Z’ is 90, ASCII value of ‘[‘ is 91). Note that character variables can be incremented but not decremented and even so only plain ASCII characters (a-z and A-Z) are supported. Incrementing/decrementing other character variables has no effect, the original string is unchanged.
The Mystery of Value Appearance
You’re a real array master in PHP, admit it. Don’t be shy. You already know everything about how to create, manage, and delete arrays. Nonetheless, the next example might surprise you at first sight. Often you work with arrays and need to search if a given value is in an array. PHP has a function for this,in_array()
. Let’s see it in action:
<?php
$array = array(
'isReady' => false,
'isPHP' => true,
'isStrange' => true
);
var_dump(in_array('sitepoint.com', $array));
What will be the output? Place your bets and let’s check it.
trueIsn’t this a little bit strange? We have an associative array where its values are all boolean and if we search for a string, we got
true
. Has this value magically appeared? Let’s see another example.
<?php
$array = array(
'count' => 1,
'references' => 0,
'ghosts' => 1
);
var_dump(in_array('aurelio', $array));
And what we get is…
trueOnce again the
in_array()
function returns true. How is this possible?
You’re experiencing one of both best and worst, loved and hated PHP features. PHP isn’t strongly typed and this is where the error starts. In fact, all the following values, if compared in PHP, are considered the same unless you use the identity operator:
- 0
- false
- “”
- “0”
- NULL
- array()
in_array()
function uses the loose comparison, a non-empty (""
) and non-zero-filled ("0"
) string is equal to true
and to all non-zero numbers (like 1
). Hence, in the first example we got true because 'sitepoint.com' == true
, while in the second we have 'aurelio' == 0
.
To solve the problem you’ve to use the third and optional parameter of in_array()
that allows you to compare the values strictly. So, if we write:
<?php
$array = array(
'count' => 1,
'references' => 0,
'ghosts' => 1
);
var_dump(in_array('aurelio', $array, true));
we’ll finally get false
as we expect!
Conclusions
Throughout this article you’ve seen some strange and unexpected behaviors you might experience while using PHP. The lessons to take away from these examples are:- Never trust floating point numbers
- Double check what data type you’ve before using them in operations
- Be aware of the problems of loose comparisons and loose data types
Frequently Asked Questions (FAQs) about PHP
What are some of the strange facts about PHP that most developers don’t know?
PHP, being a versatile and widely-used language, has some peculiarities that even seasoned developers might not be aware of. For instance, PHP allows for variable variables, where the name of a variable can be stored in another variable. Also, PHP has a unique way of comparing non-numeric strings, where it converts them to numbers and then compares the numbers. Lastly, PHP has a unique error suppression operator ‘@’, which can be used to suppress error messages.
What are some weird operators in PHP?
PHP has a few operators that might seem strange to developers coming from other languages. For instance, the ‘===’ operator checks for both value and type equality, while the ‘==’ operator only checks for value equality. Another peculiar operator is the ‘spaceship’ operator ‘<=>’, which can be used for three-way comparison.
What are some interesting facts about PHP?
PHP has a rich history and a plethora of interesting facts. For instance, PHP originally stood for ‘Personal Home Page’, but it now stands for ‘PHP: Hypertext Preprocessor’, a recursive acronym. Also, PHP was originally designed for tracking visits to Rasmus Lerdorf’s online resume, but it has now evolved into a full-fledged programming language.
What are some hilarious code snippets in PHP?
PHP, like any other language, has its share of hilarious code snippets. For instance, the ‘goto’ statement, which is generally considered a bad practice, can lead to some funny and confusing code. Also, PHP allows for some strange function names like ‘die’ and ‘explode’, which can lead to some humorous code.
What are some facts about PHP that make it unique?
PHP is unique in many ways. For instance, it is one of the few languages that was designed specifically for web development. Also, PHP has a large and active community, which means that it is constantly being updated and improved. Lastly, PHP is open-source, which means that anyone can contribute to its development.
How does PHP handle non-numeric string comparison?
When comparing non-numeric strings, PHP converts them to numbers and then compares the numbers. If the string does not start with a number, it is converted to 0. This can lead to some unexpected results. For instance, ’10 apples’ is considered equal to ’10 oranges’ because both strings are converted to the number 10.
What is the error suppression operator in PHP?
The error suppression operator in PHP is ‘@’. It can be used to suppress error messages that would otherwise be displayed. However, it is generally considered a bad practice to use this operator, as it can make debugging more difficult.
What is the spaceship operator in PHP?
The spaceship operator in PHP is ‘<=>’. It can be used for three-way comparison. It returns -1 if the left operand is less than the right, 0 if they are equal, and 1 if the left operand is greater than the right.
What is the history of PHP?
PHP was originally designed by Rasmus Lerdorf in 1994 for tracking visits to his online resume. It originally stood for ‘Personal Home Page’, but it now stands for ‘PHP: Hypertext Preprocessor’. Over the years, PHP has evolved into a full-fledged programming language and is now used by millions of websites worldwide.
What is the community like for PHP?
PHP has a large and active community. This means that there are plenty of resources available for learning and troubleshooting. Also, because PHP is open-source, anyone can contribute to its development. This has led to a constant stream of updates and improvements to the language.
I'm a (full-stack) web and app developer with more than 5 years' experience programming for the web using HTML, CSS, Sass, JavaScript, and PHP. I'm an expert of JavaScript and HTML5 APIs but my interests include web security, accessibility, performance, and SEO. I'm also a regular writer for several networks, speaker, and author of the books jQuery in Action, third edition and Instant jQuery Selectors.