On Thu, Apr 4, 2024 at 2:28 PM Rowan Tommins [IMSoP] <imsop....@rwec.co.uk>
wrote:

>
>
> I haven't followed the discussion in the other thread, but I'm not sure
> what the use case would be for a "fixed scale decimal" that followed
> those rules.
>
> As mentioned before, the use case I've encountered is money
> calculations, where what people want to fix is the smallest unit of
> account - e.g. €0.01 for practical currency, or €0.0001 for detailed
> accounting / trading.
>
> If I write $total = 1.03_d2; $perPerson = $total / 2; I want a result of
> 0.51_d2 or 0.52_d2 - that's why I specified a scale of 2 in the first
> place.
>

Well, firstly most of the financial applications that I've worked in (I
work for a firm that writes accounting software right now) do not calculate
intermediate steps like this with fixed precision, or even have an interest
in doing so. They generally want maximum precision that is computationally
reasonable, and then round it according to their preferred method at the
end. Doing the calculations as you are suggesting would introduce a maximum
error of several cents/pence/etc. after only two or three calculations,
which is utterly useless for most applications that deal with money.

Truly "fixed-precision" is not something that decimal should even try to
be, in my opinion. The use cases where you CANNOT simply round the result
at the end to fit your display output or your storage location are very
minimal.


> If I want an accurate result of 0.515_d3, I would just specify 1.03_d,
> since the scale hasn't had any effect on the result.
>
> If I want a lossless split into [0.51_d2, 0.52_d2] I still need a
> function to exist somewhere, whether you spell that $total->split(2), or
> decimal_split($total, 2), etc. So it seems safer to also have
> $total->div(2, Round::DOWN) or decimal_div($total, 2, Round::DOWN) and
> have $total / 2 give an error.
>

I mean, what you are describing is how such OBJECTS are designed in other
languages like Python, but not scalars. Python also has (almost completely
unrestricted) userland operator overloading, which PHP does not, which
further makes the comparison a little murky.

This kind of precision restriction isn't something you would place on an
individual value, it's something you would place on all calculations.
That's why in Python this is done with a global runtime setting using
`getContext().perc` and `getContext().rounding`. A particular value having
a precision of X doesn't imply anything concrete about a calculation that
uses that value necessarily.


> Possibly, it could only error if the result doesn't fit in the scale, so
> that this would be fine: $total = 11.00_d2; $perPerson = $total / 2;
> assert($perPerson === 5.50_d2)
>
> Or possibly, it would just be an error to perform division on a fixed
> scale decimal, but allowed on a variable-fixed scale decimal.
>

Maybe we're just not understanding each other. Are you opposed to the idea
of doing this as a scalar? It certainly feels that way. This feels more
like an argument in favor of doing object-like numerics for this. I suppose
that isn't really that strange either, because as I noted such a value will
almost certainly need to be refcounted because it will not fit into the 64
bits available for a zval no matter what underlying library is used to
perform the math.

Jordan

Reply via email to