On Sat, Mar 30, 2024 at 5:09 PM Saki Takamachi <s...@sakiot.com> wrote:
> Hi Jordan, > > Your opinion may be reasonable given the original BCMath calculation > order. That is, do you intend code like this? > > Signature: > ``` > // public function __construct(string|int $number) > // public function getNumber(?int $scale = null): string > ``` > > Add: > ``` > // public function add(Number|string|int $number): string > > $num = new Number('1.23456'); > $num2 = new Number('1.23'); > > $add = $num + $num2; > $add->getNumber(); // '2.46456' > $add->getNumber(1); // ‘2.4' > > $add = $num->add($num2); > $add->getNumber(); // '2.46456' > $add->getNumber(1); // '2.4' > ``` > > Div: > ``` > // public function div(Number|string|int $number, int $scaleExpansionLimit > = 10): string > > > // case 1 > $num = new Number('0.0001'); > $num2 = new Number('3'); > > $div = $num / $num2; // scale expansion limit is always 10 > $div->getNumber(); // '0.0000333333333' > > $div = $num->div($num2, 20); > $div->getNumber(); // '0.00003333333333333333333' > $div->getNumber(7); // ‘0.0000333' > > > // case 2 > $num = new Number('1.111111'); > $num2 = new Number('3'); > > $div = $num->div($num2, 3); > $div->getNumber(); // '0.370' > $div->getNumber(7); // ‘0.3700000' > ``` > > Since the scale can be inferred for everything other than div, a special > argument is given only for div. > > Regards. > > Saki Something like the signature for `getNumber()` in this example would be a decent solution. Operations which have ambiguous scale (of which truly only div is in the BCMath library) should *require* scale in the method that calls the calculation, however for consistency I can certainly see the argument for requiring it for all calculation methods. The issue is how you want to handle that for operator overloads, since you cannot provide arguments in that situation. Probably the most sensible way (and I think the way I handled it as well in my library) is to look at both the left and right operand, grab the calculated scale of the input for both (or the set scale if the scale has been manually set), and then calculate with a higher scale. If internally it produces a rounded result, the calculation should be done at `$desireScale + 2` to avoid compound rounding errors from the BCMath library and then the implementation. If the result is truncated, the calculation should be done at `$desiredScale + 1` to avoid calculating unnecessary digits. So we have multiple usage scenarios and the behavior needs to remain consistent no matter which usage occurs, and what order the items are called in, so long as the resulting calculation is the same. **Method Call** $bcNum = 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 scale of numerator is 7, calculate with scale of 8 then truncate **Operators** $bcNum = new Number('1.0394567'); // Input scale is implicitly 7 $bcNum / '1.2534'; // Implicit scale of denominator is 4, Implicit scale of numerator is 7, calculate with scale of 8 then truncate 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 for the same calculation, and never reducing scale UNLESS it is told to do so in the calculation step OR during the value retrieval. Jordan