Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:121999 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 94165 invoked from network); 13 Dec 2023 08:37:41 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 13 Dec 2023 08:37:41 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 9C8E4180061 for ; Wed, 13 Dec 2023 00:37:56 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DMARC_MISSING, HTML_MESSAGE,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail1.25mail.st (mail1.25mail.st [206.123.115.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Wed, 13 Dec 2023 00:37:55 -0800 (PST) Received: from smtpclient.apple (unknown [49.48.223.90]) by mail1.25mail.st (Postfix) with ESMTPSA id 4E0416037E; Wed, 13 Dec 2023 08:37:32 +0000 (UTC) Message-ID: <21E561F4-8893-4825-A2A9-15B305376864@koalephant.com> Content-Type: multipart/alternative; boundary="Apple-Mail=_725C9D94-5C77-4AEE-BE79-9B16D9056E09" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3774.300.61.1.2\)) Date: Wed, 13 Dec 2023 15:37:18 +0700 In-Reply-To: <18c42fdbb30.2831.17a3710df6d58f02ca570cc47e197a63@interi.co> Cc: internals@lists.php.net To: Alex Pravdin References: <18c42fdbb30.2831.17a3710df6d58f02ca570cc47e197a63@interi.co> X-Mailer: Apple Mail (2.3774.300.61.1.2) Subject: Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type From: php-lists@koalephant.com (Stephen Reay) --Apple-Mail=_725C9D94-5C77-4AEE-BE79-9B16D9056E09 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii > On 7 Dec 2023, at 13:36, Alex Pravdin wrote: >=20 > Hello internals, >=20 >=20 > This is the second round of the discussion regarding arbitrary = precision scalar type integration into PHP. The previous part: = https://marc.info/?l=3Dphp-internals&m=3D168250492216838&w=3D2 was = initiated by me before deep diving into the work with decimals in PHP. = After 6 months of working, I would like to update my proposal taking = into account my experience and the previous discussion. >=20 > Today's alternatives and their problems are the following. >=20 > bcmath: > - Workaround: using string type. > - Unintuitive function calls instead of regular math operations. > - Unintuitive strings instead of numbers. People want to work with = numbers. > - Can not use proper type-hinting. > - Can use PHP's basic type coercions. >=20 > Ext-decimal: > - Third-party extension. > - Workaround: implements the Decimal class that allows basic regular = math operations. > - Requires using class methods for the rest of math operations. > - The latest release was in 2019 and there's a danger that it will be = unmaintained and not compatible with the future PHP releases. > - The php-decimal documentation website is currently down. > - Since objects are always casted to true when not null, "(bool) = Decimal(0)" will equal to true which is not intuitive. > - IDEs are often confused when you use math operations on objects = while the code works fine. >=20 > GMP: > - Workaround: implements the GMP class that allows basic math = operations. > - Requires using separate functions for the rest of operations. >=20 > - Objects are always casted to true, GMP(0) will equal to true. >=20 >=20 > Accounting for all of the above, I suggest adding a native numeric = scalar arbitrary precision type called "decimal". Below are the = preliminary requirements for implementation. >=20 >=20 > Decimal values can be created from literals by specifying a modifier = or using the (decimal) typecast: >=20 > $v =3D 0.2d; > $v =3D (decimal) 0.2; // Creates a decimal value without intermediary = float >=20 > It uses the precision and scale defined in php.ini. >=20 > The "decimal" typehint allows to define custom precision and scale: = decimal(20,5). It accepts regular expressions returning ints in the = execution context. It accepts int constants and literals in class field = and function argument definitions. >=20 > New functions added: get_scale and get_precision to return = corresponding values about a decimal value. >=20 > If decimal value with different scale and precision is going to be = assigned to a variable or parameter with smaller scale or precision, it = first tries to convert the value. If it's not possible, then an = exception is thrown like "Can not convert decimal (a, b) xxxxx.yyyy to = decimal(c, d)". If possible, it performs the conversion and generates a = warning like "Assigning decimal(a, b) to decimal(c, d) may be not = possible with some values". >=20 > It works the same as "float" in terms of its usage and type casting = except for one thing. Float value can be passed to a decimal argument or = typecasted with a warning like "Float to decimal conversion may incur = unexpected results". >=20 > Decimal to float conversion is allowed and smooth: >=20 > function f (float $value) {} >=20 > f(0.2); >=20 > f(0.2d); // allowed with no warnings >=20 >=20 > Function "str_to_decimal" added to convert string representation of = numbers to decimals. >=20 >=20 > Typecast from string to decimal works the same as the "str_to_decimal" = function. >=20 > Function "float_to_decimal" added to explicitly convert floats to = decimals. It performs float to string conversions using php.ini settings = as defaults but also accepts parameters to configure the conversion. = Then, it converts string to decimal. Since the main problem of float to = decimal conversion is that we don't know the exact result until we use = some rounding when transforming it to a human-readable format, it looks = like the step of the conversion to a string is inevitable. Any more = optimized algorithms are welcome. >=20 > Explicit typecast from float to decimal works the same as = "float_to_decimal" function with all default values but also throws a = warning. This is to encourage users to use explicit conversion with the = "float_to_decimal" function and control the results. >=20 > Literal numbers in the code are converted to floats by default. If = prepended by the "(decimal)" typecast, the decimal result is produced = without an intermediary float. >=20 > New declare directive "default_decimal" is added. When used, literals = and math operations return decimal by default instead of float. This is = to simplify creating source files working with decimals only. >=20 > New language construct "as_decimal()" is added to produce decimal math = results for literals and math operations instead of float without = intermediary float: >=20 > $var =3D 5 / 2; // returns float 2.5 > $var =3D as_decimal(5 / 2); // returns decimal 2.5 >=20 > This is a kind of "default_decimal" for a specific operation. >=20 > If mixed float and decimal operands are used in a math operation, = decimal is converted to float by default. If "default_decimal" directive = or "as_decimal()" construct is used, float is converted to decimal (with = a warning): >=20 > $f =3D (float) 0.2; > $d =3D (decimal) 0.2; >=20 > $r =3D $f + $d; // returns float result by default > $r =3D as_decimal($f + $d); // returns decimal result with a warning = about implicit float to decimal conversion >=20 > All builtin functions that currently accept float also accept decimal. = So users don't need to care about separate function sets, and PHP = developers don't need to maintain separate sets of functions. If such = functions get the decimal parameter, they return decimal. If they have = more than one float parameter and mixed float and decimal passed, = decimals converted to float by default. If "default_decimal" or = "as_decimal" used, float is converted to decimal with the warning. >=20 >=20 > The new type uses libmpdec internally to perform decimal calculations = (same as Python). >=20 >=20 > All of the points above are subject to discussions, it is not an RFC = candidate right now. So please share your opinions. >=20 > I know that the implementation of this will require a lot of work. But = I don't think this is a stopper from formulating the requirements. = Sometimes, any project requires big changes to move forward. I'm pretty = sure this functionality will move PHP to the next level and expand its = area of applications. My thoughts here are mostly from the user's = perspective, I'm not so familiar with PHP internal implementation. But I = think this feature can be a good goal for PHP 9. >=20 >=20 > -- > Best regards, > Alex Pravdin Hi, While I do think it would be beneficial to have a built-in `decimal` = type, regarding ext-decimal, I think some of the points raised may be = outdated? The documentation site seems to have moved to = https://php-decimal.github.io , which = also indicates that it implements operator overrides. Cheers Stephen=20 --Apple-Mail=_725C9D94-5C77-4AEE-BE79-9B16D9056E09--