> On 7 Dec 2023, at 13:36, Alex Pravdin <alex.prav...@interi.co> wrote: > > Hello internals, > > > This is the second round of the discussion regarding arbitrary precision > scalar type integration into PHP. The previous part: > https://marc.info/?l=php-internals&m=168250492216838&w=2 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. > > Today's alternatives and their problems are the following. > > 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. > > 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. > > GMP: > - Workaround: implements the GMP class that allows basic math operations. > - Requires using separate functions for the rest of operations. > > - Objects are always casted to true, GMP(0) will equal to true. > > > 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. > > > Decimal values can be created from literals by specifying a modifier or using > the (decimal) typecast: > > $v = 0.2d; > $v = (decimal) 0.2; // Creates a decimal value without intermediary float > > It uses the precision and scale defined in php.ini. > > 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. > > New functions added: get_scale and get_precision to return corresponding > values about a decimal value. > > 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". > > 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". > > Decimal to float conversion is allowed and smooth: > > function f (float $value) {} > > f(0.2); > > f(0.2d); // allowed with no warnings > > > Function "str_to_decimal" added to convert string representation of numbers > to decimals. > > > Typecast from string to decimal works the same as the "str_to_decimal" > function. > > 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. > > 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. > > 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. > > 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. > > New language construct "as_decimal()" is added to produce decimal math > results for literals and math operations instead of float without > intermediary float: > > $var = 5 / 2; // returns float 2.5 > $var = as_decimal(5 / 2); // returns decimal 2.5 > > This is a kind of "default_decimal" for a specific operation. > > 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): > > $f = (float) 0.2; > $d = (decimal) 0.2; > > $r = $f + $d; // returns float result by default > $r = as_decimal($f + $d); // returns decimal result with a warning about > implicit float to decimal conversion > > 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. > > > The new type uses libmpdec internally to perform decimal calculations (same > as Python). > > > All of the points above are subject to discussions, it is not an RFC > candidate right now. So please share your opinions. > > 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. > > > -- > 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 <https://php-decimal.github.io/>, which also indicates that it implements operator overrides. Cheers Stephen