Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:122853 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id 79D961A009C for ; Tue, 2 Apr 2024 11:26:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1712057232; bh=jOv21NkM4Vt63yNYi6h8EtS43H9S70Ggq6EqR39pJww=; h=Subject:From:In-Reply-To:Cc:Date:References:To:From; b=DtmwpzfMviKM07Y4bOhxi+hmFhFpFOuXeroeMgTnxLhkdakwuHzYCVZramgF+E5wy 0JQonke5NF3xG08g6mn9tvLSNBLf0sQXYWjh/A094wh5GfJoEbLTwg/IWntIEefCNW cxfKH8dveV6gF3Jv1Z3OKHYbhAMpEO4yRV7+opVAW/6soVNCd/lHuMpA4f42Jnzm9o nZ34Q3CT7eV+Qt+XLQhjqAtc1hj97ShBXiimzWzhC+FyVWMqVrJz2c0b27Kn9tKyYz yp5Gmsx5aJXOIIfxDM4Top03O4IvvYeZRWjuTy+V8ozUZT+k5xo1R3PgcagMa4vewt bez68abxMH42Q== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id BBE2E180082 for ; Tue, 2 Apr 2024 11:27:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail.sakiot.com (mail.sakiot.com [160.16.227.216]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Tue, 2 Apr 2024 11:27:09 +0000 (UTC) Received: from smtpclient.apple (220.125.214.202.rev.vmobile.jp [202.214.125.220]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by mail.sakiot.com (Postfix) with ESMTPSA id 4132F40204; Tue, 2 Apr 2024 20:26:39 +0900 (JST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=sakiot.com; s=default; t=1712057199; bh=jOv21NkM4Vt63yNYi6h8EtS43H9S70Ggq6EqR39pJww=; h=Subject:From:In-Reply-To:Cc:Date:References:To:From; b=HwnS9lmZ9gr9OuXRZuO77etHeIl6H3EFZkTsOp/ZL2n4rPx5ecTsnGF0tYCUvJjzZ J9rhmudWdW7Ky+uJs0DT02fVI0EGP86mg8Gc3xT/4YE07kQ9rgVBPP4NRuTkTBpGvI drGOCds52HTsT7VE6/oS6JiDziNtJQcrPn+lHUSQ= Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net Mime-Version: 1.0 (1.0) Subject: Re: [PHP-DEV] [RFC] [Discussion] Support object type in BCMath In-Reply-To: Cc: Jordan LeDoux , Aleksander Machniak , php internals Date: Tue, 2 Apr 2024 20:26:26 +0900 Message-ID: References: To: Lynn X-Mailer: iPhone Mail (21D61) From: saki@sakiot.com (Saki Takamachi) Hi Jordan, Lynn, > Something like the signature for `getNumber()` in this example would be a d= ecent solution. Operations which have ambiguous scale (of which truly only d= iv is in the BCMath library) should *require* scale in the method that calls= the calculation, however for consistency I can certainly see the argument f= or requiring it for all calculation methods. The issue is how you want to ha= ndle that for operator overloads, since you cannot provide arguments in that= situation. >=20 > Probably the most sensible way (and I think the way I handled it as well i= n my library) is to look at both the left and right operand, grab the calcul= ated scale of the input for both (or the set scale if the scale has been man= ually set), and then calculate with a higher scale. If internally it produce= s a rounded result, the calculation should be done at `$desireScale + 2` to a= void compound rounding errors from the BCMath library and then the implement= ation. If the result is truncated, the calculation should be done at `$desir= edScale + 1` to avoid calculating unnecessary digits. >=20 > So we have multiple usage scenarios and the behavior needs to remain consi= stent no matter which usage occurs, and what order the items are called in, s= o long as the resulting calculation is the same. >=20 > **Method Call** > $bcNum =3D new Number('1.0394567'); // Input scale is implicitly 7 > $bcNum->div('1.2534', 3); // Resulting scale is 3 > $bcNum->div('1.2534'); // Implicit scale of denominator is 4, Implicit sca= le of numerator is 7, calculate with scale of 8 then truncate >=20 > **Operators** > $bcNum =3D new Number('1.0394567'); // Input scale is implicitly 7 > $bcNum / '1.2534'; // Implicit scale of denominator is 4, Implicit scale o= f numerator is 7, calculate with scale of 8 then truncate >=20 > This allows you to perhaps keep an input scale in the constructor and also= maintain consistency across various calculations. But whatever the behavior= is, it should be mathematically sound, consistent across different syntax f= or the same calculation, and never reducing scale UNLESS it is told to do so= in the calculation step OR during the value retrieval. > I'm inexperienced when it comes to maths and the precision here, but I do h= ave some experience when it comes to what the business I work for wants. I'v= e implemented BCMath in a couple of places where this kind of precision is n= ecessary, and I found that whenever I do divisions I prefer having at least 2= extra digits. Would it make sense to internally always just store a more ac= curate number? For things like additions/multiplications/subtractions it cou= ld always use the highest precision, and then for divisions add like +3~6 or= something. Whenever you have numbers that have a fraction like `10.5001` it= makes sense to set it to 4, but when you have `10` it suddenly becomes 0 wh= en implicitly setting it.=20 >=20 > For the following examples assume each number is a BcNum: > When doing something like `10 * 10.0000 * 10.000000000` I want the end res= ult to have a precision of at least 9 so I don't lose information. When I do= `((10 / 3) * 100) * 2` I don't want it to implicitly become 0, because the p= recision here is important to me. I don't think using infinite precision her= e is a reasonable approach either. I'm not sure what the correct answer is, p= erhaps it's just "always manually set the precision"? Thanks for the important perspective feedback. One thing I overlooked: if the exponent of pow is negative, the scale of the= result becomes unpredictable, just like with div. e.g. ``` 3 ** -1 =3D 0.333333..... ``` Also, an idea occurred to me while reading your comments. The current assumption is that a Number always holds a single value. How if w= e made it so that it held two values? They are the numerator and the denomin= ator. This means that when we do division, no division is done internally, but we a= ctually multiply the denominator. At the very end of the process, when conve= rting to string, any reserved division is performed according to the specifi= ed scale. If we have the option of not specifying a scale when converting to a string,= it may be preferable to convert based on an implicit scale. Regards. Saki=