Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:58580 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 16467 invoked from network); 4 Mar 2012 15:29:42 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 4 Mar 2012 15:29:42 -0000 Authentication-Results: pb1.pair.com header.from=glopes@nebm.ist.utl.pt; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=glopes@nebm.ist.utl.pt; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain nebm.ist.utl.pt from 193.136.128.21 cause and error) X-PHP-List-Original-Sender: glopes@nebm.ist.utl.pt X-Host-Fingerprint: 193.136.128.21 smtp1.ist.utl.pt Linux 2.6 Received: from [193.136.128.21] ([193.136.128.21:43798] helo=smtp1.ist.utl.pt) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 41/01-12048-46A835F4 for ; Sun, 04 Mar 2012 10:29:41 -0500 Received: from localhost (localhost.localdomain [127.0.0.1]) by smtp1.ist.utl.pt (Postfix) with ESMTP id 82A2E7000436; Sun, 4 Mar 2012 15:29:37 +0000 (WET) X-Virus-Scanned: by amavisd-new-2.6.4 (20090625) (Debian) at ist.utl.pt Received: from smtp1.ist.utl.pt ([127.0.0.1]) by localhost (smtp1.ist.utl.pt [127.0.0.1]) (amavisd-new, port 10025) with LMTP id ATt+bzRON+zs; Sun, 4 Mar 2012 15:29:37 +0000 (WET) Received: from mail2.ist.utl.pt (mail.ist.utl.pt [IPv6:2001:690:2100:1::8]) by smtp1.ist.utl.pt (Postfix) with ESMTP id D37247000433; Sun, 4 Mar 2012 15:29:36 +0000 (WET) Received: from damnation.nl.lo.geleia.net (damnation.nl.lo.geleia.net [IPv6:2001:470:94a2:4:4866:11bc:1688:8089]) (Authenticated sender: ist155741) by mail2.ist.utl.pt (Postfix) with ESMTPSA id 788F92005415; Sun, 4 Mar 2012 15:29:34 +0000 (WET) Content-Type: text/plain; charset=utf-8; format=flowed; delsp=yes To: "Pierre Joye" , "Anthony Ferrara" Cc: internals@lists.php.net References: Date: Sun, 04 Mar 2012 16:29:30 +0100 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.61 (Win32) Subject: Re: [PHP-DEV] Patches for Review From: glopes@nebm.ist.utl.pt ("Gustavo Lopes") On Sun, 04 Mar 2012 15:02:23 +0100, Anthony Ferrara wrote: >>> In sum, I think the rule that if a mathematical operation involves a >>> float, the result should be a float ought to be kept. >> >> Yes, it is a must. > > Well, I'm not so sure about that. > > If you look at the docs of pow(), it describes the return type as > "base raised to the power of exp. If the result can be represented as > integer it will be returned as type integer, else it will be returned > as type float.". > > That's not the current behavior. pow((float) 2, 1) returns float(2). > If you want to update the docs instead of the code, then that's fine. You're reading too much into the documentation. The intention of that phrase seems to be if the result overflows, it will a float instead (just like when you add two large integers, for instance). Yes, the plain text doesn't preclude your interpretation, but it's not supported by the implementation or the general behavior of mathematical operators in PHP. By all means, change it in order to make it more clear. > However, this can lead to precision loss in a number of cases (like > pow(2, (float) 55) which is not representable exactly by a float, and > hence cause data-loss. Whereas converting to an integer allows (on 64 > bit platforms) an exact representation. You're making a critical error here. float(55.) is in fact different from int(55). Float values have a rounding error associated, while integers don't. The accuracy of float(55.) is 14.2142, which means the uncertainty is 6.10623*10^-15, or that float(55.) = 55 +- 3.05311*10^-15. Mathematical operations will only increase the (relative) error and therefore decrease the precision. This is an example with Mathematica's arbitrary precision numbers (NOT machine precision numbers, even though I'm setting the arbitrary precision to $MachinePrecision); this keeps track of the accumulated errors: In[30]:= SetPrecision[55, $MachinePrecision] // Precision Out[30]= 15.9546 In[31]:= 2^SetPrecision[55, $MachinePrecision] // Precision Out[31]= 14.3734 This means that if you do 2^55., the result will have total uncertainty: In[34]:= 2^SetPrecision[55, $MachinePrecision] // 10^-Accuracy[#] & Out[34]= 152.492 Take your example: var_dump((int) (pow(2, (float) 55) - 1)); You're adding 1 to a result that has a total uncertainty of more than 152... It's pointless, don't you think? Of course, PHP doesn't keep track of errors, and the reason subtracting 1 has no effect is because the rounding error itself in the result is already larger than 2: In[45]:= 2^55. // 10^-Accuracy[#] & Out[45]= 4. > [...] > Additionally, I thought the whole point of type juggling in PHP was > such that the type didn't matter? So that a float and an int are the > same from a usage standpoint? This is a very vague statement. "Doesn't matter" for what? We have different types for integers and floats, 1. and 1 are different things and this is reflected in several places. What type juggling does is that one *one specific type is expected*, but another one is given, PHP tries to convert the result. This doesn't mean the types are "implementation details". > But this is a case where the exact same > input (just type is different) leads to different output. Which I > believe is inconsistent and incorrect. > > But if the consensus is otherwise, that's fine... > -- Gustavo Lopes