Numerical strings comparison
Why PHP sometimes consider two apparently different strings equal? '8000058E-1345823534' == '8000079E-1468962218'
is true
for example.
This kind of questions often come up on PHP forums, so I decided to explain it in detail.
There are two reasons for this
Inevitable casting
First, when comparing strings, and a string looks like a number, it is converted to a number for a comparison.
But why PHP does that? The reason is simple, though it took me quite a time to realize. PHP is a loosely typed language, allowing intermixing variables of different type in a single expression. In HTTP, every data value is a string. So all PHP input variables are. Old database drivers also returned all data types as strings. So you can tell that if a user enters 100
in the form field and 20
is the result from database, we cannot compare these values right away (to tell which is bigger): given both are strings, the result will be quite discouraging.
Therefore, when we have to deal with numbers, inevitably PHP must "detect" numbers in order to compare them properly, because, although to test for the equality it is not that important, but to test whether a number is less than or greater than another, it is critical to compare them as numbers, not as strings, because string "2" is greater than string "1000". So now you can tell that if a string value looks like a number, it is converted to a number for a comparison.
Given there is a single function to handle all comparisons, such a magic is involved with "equal to" comparisons as well.
Scientific notation
Second, a string '8000079E-1468962218'
looks like a floating point number in the scientific notation which is understood by PHP. And as it was explained above, PHP tries to convert it to a number. So for example "1000" == "1e3"
is true
.
But '8000058E-1345823534'
and '8000079E-1468962218'
look entirely different even for numbers? Why they considered equal anyway?
Because these numbers are so small, 1468962218 zeroes after the decimal delimiter! Given floating point operations are inherently imprecise, the resulting value is effectively a zero.
So you can tell that there is a more confusing statement, '8000058E-1345823534' == '0'
which is also true
.
In the end, '8000058E-1345823534' == '8000079E-1468962218'
turns out to be 0 == 0
which perfectly explains the result.
Conclusion
This is why you are encouraged to use the strict comparison operator, ===
instead of ==
, because when the former is used, no such magic is ever involved, values get compared as is.
Related articles:
- Relative and absolute paths, in the file system and on the web server.
- PHP error reporting
- Do you really need to check for both isset() and empty() at the same time?
- What's wrong with popular articles telling you that foo is faster than bar?
- MVC in simpler terms or the structure of a modern web-application
- How to get a single player's rank based on the score
- Articles
- Do you abuse the null coalescing operator (and isset/empty as well)?
- Operator precedence or how does 'or die()' work.
- Why should I use prepared statements if escaping is safe?
- Do generators really reduce the memory usage?
- How to make Stack Overflow a nice place
- Iterating over array getting look-ahead items along
- How to debug small PHP programs
Add a comment
Please refrain from sending spam or advertising of any sort.
Messages with hyperlinks will be pending for moderator's review.
Markdown is now supported:
>
before and an empty line after for a quote