Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:59873 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 59417 invoked from network); 13 Apr 2012 11:01:46 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 13 Apr 2012 11:01:46 -0000 Authentication-Results: pb1.pair.com smtp.mail=glopes@nebm.ist.utl.pt; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=glopes@nebm.ist.utl.pt; sender-id=unknown Received-SPF: error (pb1.pair.com: domain nebm.ist.utl.pt from 193.136.128.22 cause and error) X-PHP-List-Original-Sender: glopes@nebm.ist.utl.pt X-Host-Fingerprint: 193.136.128.22 smtp2.ist.utl.pt Linux 2.6 Received: from [193.136.128.22] ([193.136.128.22:54015] helo=smtp2.ist.utl.pt) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 44/74-35770-697088F4 for ; Fri, 13 Apr 2012 07:01:43 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by smtp2.ist.utl.pt (Postfix) with ESMTP id B05A970004AB; Fri, 13 Apr 2012 12:01:39 +0100 (WEST) X-Virus-Scanned: by amavisd-new-2.6.4 (20090625) (Debian) at ist.utl.pt Received: from smtp2.ist.utl.pt ([127.0.0.1]) by localhost (smtp2.ist.utl.pt [127.0.0.1]) (amavisd-new, port 10025) with LMTP id 9tz8ETKGSCZ3; Fri, 13 Apr 2012 12:01:39 +0100 (WEST) Received: from mail2.ist.utl.pt (mail.ist.utl.pt [IPv6:2001:690:2100:1::8]) by smtp2.ist.utl.pt (Postfix) with ESMTP id ED4EA70004B5; Fri, 13 Apr 2012 12:01:38 +0100 (WEST) Received: from slws007.slhq.int (a79-168-248-114.cpe.netcabo.pt [79.168.248.114]) (Authenticated sender: ist155741) by mail2.ist.utl.pt (Postfix) with ESMTPSA id 717D1202252C; Fri, 13 Apr 2012 12:01:38 +0100 (WEST) Content-Type: text/plain; charset=utf-8; format=flowed; delsp=yes To: "marius adrian popa" , "Pierre Joye" Cc: "PHP Developers Mailing List" References: Date: Fri, 13 Apr 2012 13:01:36 +0200 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Organization: =?utf-8?Q?N=C3=BAcleo_de_Eng=2E_Biom=C3=A9di?= =?utf-8?Q?ca_do_I=2ES=2ET=2E?= Message-ID: In-Reply-To: User-Agent: Opera Mail/11.62 (Win32) Subject: Re: [PHP-DEV] '9223372036854775807' == '9223372036854775808' From: glopes@nebm.ist.utl.pt ("Gustavo Lopes") On Fri, 13 Apr 2012 11:48:10 +0200, Pierre Joye wrote: > On Fri, Apr 13, 2012 at 11:40 AM, marius adrian popa > 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