On Tue, Dec 12, 2023 at 2:04 PM G. P. B. <george.bany...@gmail.com> wrote: > > On Fri, 8 Dec 2023 at 10:14, Alexander Pravdin <alex.prav...@interi.co> > wrote: > > > On Thu, Dec 7, 2023 at 11:36 PM G. P. B. <george.bany...@gmail.com> wrote: > > > > - Objects are always casted to true, GMP(0) will equal to true. > >>> > >> > >> This is incorrect, GMP object do _not_ support casts to bool > >> See https://3v4l.org/LHpD1 > >> > > > > This is weird. Any PHP user would expect that a zero number can be easily > > casted to boolean false. This is also why I think we need a scalar decimal > > type. > > > > Internal objects can overload casts, SimpleXML overloads the boolean cast > already. > We could add this to GMP to return false for 0. > > > > 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 > >>> > >> > >> I disagree with this part, floats can not represent decimal values > >> properly e.g. > >> $f1 = 0.1; > >> $f2 = 0.2; > >> $f3 = 0.3; > >> var_dump($f1 + $f2 === $f3); > >> > > will return false. > >> As such, floats are not at all compatible with decimals. > >> > > > > Yes, I know that. I mentioned that we can not convert float to decimal > > without an intermediate value where we apply rounding and get a > > human-readable value in some representation (string or whatsoever). > > > > My intention was to provide implicit conversion with warnings because I > > guess that the majority of end users will expect that numeric scalar types > > are interoperable. To not make them scared and point them to issues in > > their code instead of slapping their hands immediately when they run > > something that is not so correct. > > > > > > > >> Moreover, the whole point of adding a warning when implicit conversions > >> from int to float happen was to be able to warn before elevating the > >> warning to a TypeError. > >> > > > > Sorry, I'm not aware of issues of converting ints to floats. Are there any > > issues? I understand the issue of the backward conversion, but not the > > forward one. Could you add details here? > > > > I meant converting floats to int. > But you can lose precision when converting an integer to float as there are > only 53 bits for the coefficient. > > > > Therefore, introducing behaviour that warns instead of throwing a > >> TypeError is already a no-go from my PoV. > >> > > > > I'm okay with TypeErrors for float to decimal conversions as well. This is > > not a key point of my proposal. If the community prefers errors instead of > > warnings - that's also fine. > > > > > > 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. > >>> > >> > >> This behaviour is rather suboptimal, I'd rather have literals be decimals, > >> as decimals to floats should always be a reasonable implicit coercion > >> considering we already do int to float. > >> > > > > Is it optimal to perform conversions on every fractional literal? This is > > also not a key point for me and I'm okay with any implementation that the > > internals community prefers. > > > > > > > >> 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. > >>> > >> > >> Please no, no new declare directives that affect engine behaviour. > >> Strict types was already a mistake because of this IMHO. > >> > > > > I didn't know that the strict types directive was a mistake. My intention > > is to be able to write clean all-decimal units of code and not break the > > backward compatibility. The old code should work as it was before. At the > > same time, there are use cases when the whole class/project should be > > written with decimals only. As a user, I want to do that without complex > > language structures and excessive typehints or explicit conversions. The > > all-decimal code should be as clean as it is now with floats. This is why > > I proposed this directive. Can you suggest something better to achieve the > > same? > > > > The issue is that I don't think having arbitrary precision decimals as a > core language feature is a necessity compared to rational types. > A cast from rational to float wouldn't produce a large round trip, whereas > trying to figure out arbitrary precision is more difficult. > But in any case, having a declare/INI or whatever that changes the > behaviour of the engine/language is not a good design choice. > > > > [...] > > > > The new type uses libmpdec internally to perform decimal calculations > >> (same > >> > >>> as Python). > >>> > >> > >> I really don't think we need arbitrary precision decimals. > >> > > I'm also not convinced using a floating point spec is the most sensible, > >> due to the rounding errors this is going to introduce. > >> The non-arbitrary IEEE 754-2008 specification cannot describe the decimal > >> 123457.1467 exactly, which is frankly pointless. > >> > >> Decimals, or more broadly rational numbers that, outside numerical > >> computations, that are going to be used are not going to need huge > >> denominators. > >> > >> I've been thinking about this for a while, and I personally think that > >> rational numbers are just better than trying to support only decimals. > >> And considering we have 64 bits to play with for a new zval type > >> splitting the bits into a 32-bit unsigned integer for the numerator and an > >> 32-bit signed integer for the denominator should provide us with enough > >> reasonable rational numbers. > >> As any number that do not fit in this structure seems to be something > >> relegated to the world of numerical computation where floats are what are > >> mostly used anyway. > >> > > > > If you can suggest a better way of working with fractional numbers - > > please do :) But IMO limiting the language by 64 bits is not a good way. It > > is more easy to go over the limit than you may think :) Especially in some > > intermediary values while performing complex calculations. I could be > > wrong, but fractional numbers limited to 64 bits sound like a bandaid. The > > language will tell users "hey, you can do something general, but if you > > want something else please don't use me at all or involve bandaids with > > extensions". My key point is not only to allow working with decimals, but > > also to make all the alternatives useless, cover their functionality by > > builtin tools, to free users from thinking about workarounds and bandaids. > > From my POV, introducing a new decimal type that does not cover the > > GMP/bcmath/ext-decimal functionality is pointless and a waste of time. > > > > Again, the use cases for arbitrary precision numbers seems rather limited, > and having this as an extension does not seem problematic at all. > My current issue is that there is no way to represent "small" numbers such > as 0.1 or 5.8 exactly. > Arbitrary precision is a totally different ballpark, be that for integers > and/or fractional values and makes everything slow, just look at Python who > is *finally* investing time and money to make the most common numbers > (those that fit in a machine word) not be abysmally slow. > > > > [...] > > > > > > > How quickly you would be able to read something like this: > > gmp_add(gmp_mul(gmp_div(gmp_sub($value, $add), $value2, $factor, > > gmp_sin($value3), gmp_intval($value))) ? > > > This absence of intuitive readability makes the development and support > > difficult and it's better to choose another language. This is what I want > > to change and make PHP powerful enough for this kind of applications. > > > > GMP supports operator overloading, so you do not need to write this, and as > far as I see, ext/decimal *also* supports operator overloading so you can > just write it using the normal arithmetic operations. > Moreover, it supports type casts so you can just do (int) $GMP instead of > gmp_intval($GMP); > And it also supports using the comparisons operatos on it instead of using > gmp_cmp() > > The only thing that is, currently, not possible to do is a cast _to_ GMP > using (GMP), but maybe that's something that could be added to the engine > for internal objects, but I'm not sure about this. > > It seems, your main motivation to have this as a language feature is to > have access to operator overloading and casting behaviour, that internal > objects already support. > Which diminish the cost/benefit of making the engine changes, especially if > the default behaviour doesn't change and one needs to maintain effectively > two different versions of PHP depending on if it is in "decimal" or > "floating" mode, which raises a plethora of questions just in its own. > > Best regards, > > Gina P. Banyard
Hey Gina, > GMP supports operator overloading GMP kinda-sorta-most-of-the-time supports operator overloading. Sometimes ... it doesn't. I implemented a field library in PHP (for work a couple of years ago) and occasionally, overloading would cast things back to float/int and break the math. I don't have access to that code, so I don't have any examples readily available (and the fact that an extension can do overloading but we can't in user-land is a whole different can of worms which made this library ridiculously hard to work with -- we rewrote everything in Scala and never looked back). Needless to say, if I were to go into a project that required GMP, I wouldn't trust the overloading. Just my 2¢ Robert Landers Software Engineer Utrecht NL -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php