On Fri, 13 Apr 2012 11:48:10 +0200, Pierre Joye <pierre....@gmail.com> wrote:

On Fri, Apr 13, 2012 at 11:40 AM, marius adrian popa <map...@gmail.com> wrote:
Something for the weekend (flamewar)
http://www.reddit.com/r/programming/comments/s6477/9223372036854775807_9223372036854775808/
http://news.ycombinator.com/item?id=3832069

https://bugs.php.net/bug.php?id=54547


This conversation has become a quite muddled with usual controversies about the nature of PHP. Instead of engaging in that sort of discussion, I'll explain the situation.

Currently, when two strings are compared, PHP tries to do a numerical comparison first. Therefore:

var_dump("010" == "10"); //true

The current implementation, however, gives up when the numbers are too large or too small.
   Zend/zend_operators.c
   2049                                 /* Both values overflowed and have the 
same sign,
   2050                                  * so a numeric comparison would be 
inaccurate */

var_dump("1.7976931348623157e308" ==
         "1.79769313486231571e308"); //true

var_dump(1.7976931348623157e400); //INF
var_dump("1.7976931348623157e400" ==
         "1.79769313486231571e400"); //false

In this case, a string comparison is done instead (memcmp).

There are other situations where the result of the comparison may be "inaccurate" -- in the sense that two strings may be constructed as representing different numbers, but they compare equal.

* Comparing two different real numbers that map to the same double precision number:
var_dump("1.9999999999999999" == "2"); //true

* Comparing two integers that are not representable as ints and that map to the same double precision number
var_dump("9223372036854775810" == "9223372036854775811"); //true

* Comparing an integer that's representable as an int with another that's not. That is what the bug is about.
var_dump(PHP_INT_MAX); //9223372036854775807
var_dump("9223372036854775807" == "9223372036854775808"); //true

In this case, the integer is also converted to a double; if long is 64-bit wide, this will result in loss of precision and now the operand will compare equal. These two last cases are easy to detect; I wrote a patch that does that and forces a plain string comparison.

However, taking the last case an example, this is the same that happens if you compare: var_dump((int)"9223372036854775807" == (double)"9223372036854775808"); //true

So in that respect the current behavior is consistent with the comparison that would take place if the numeric strings were to be converted to ints or doubles (following the usual rules to choose between the two, i.e., if there's no decimal place or exponent, take an int unless it's too large in absolute value).

Whether the current behavior is correct depends on whether you consider (string)"9223372036854775808" to represent an integer value that, not being representable as int in PHP, should preclude a numeric comparison, or if you consider (string)"9223372036854775808" to be the same as (double)"9223372036854775808" for numeric comparison purposes. And I'm not sure here.

--
Gustavo Lopes

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to