Re: [RFC] [Discussion] Support object type in BCMath

From: Date: Sun, 31 Mar 2024 00:09:18 +0000
Subject: Re: [RFC] [Discussion] Support object type in BCMath
References: 1 2 3 4 5  Groups: php.internals 
Request: Send a blank email to internals+get-122832@lists.php.net to get a copy of this message
Hi Jordan, > For addition, it absolutely should expand scale like this, unless the constructor also defines > a default rounding type that is used in that situation. All numbers, while arbitrary, will be > finite, so addition will always be exact and known based on inputs prior to calculation. > > Treating scale like this isn't more strict, it's confusing. For instance: > > ``` > $numA = new Number('1.23', 2); > $numB = new Number('1.23456', 5); > > $expandedScale1 = $numA + $numB; // 2.46456 > $expandedScale2 = $numB + $numA; // 2.46456 > > $strictScale1 = $numA + $numB; // 2.46 assuming truncation > $strictScale2 = $numB + $numA; // 2.46456 > ``` > > I ran into this same issue with operand ordering when I was writing my operator overload RFC. > > There are ways you could do the overload implementation that would get around this for object + > object operations, but it's also mathematically unsound and probably unexpected for anyone who > is going to the trouble of using an arbitrary precision library. > > Addition and subtraction should automatically use the largest scale from all operands. Division > and multiplication should require a specified scale. > > Because of this, I'm not entirely sure that specifying a scale in the constructor is > actually a good thing. It is incredibly easy to create situations, unless the implementation in C is > VERY careful, where the operand positions matter beyond the simple calculation. Multiplication is > commutative, but division is not. This would almost certainly lead to some very difficult to track > down bugs. > > Putting scale in the constructor is similar to some of the examples of "possible misuse > cases of operator overloading" that I had to go over when I was making my RFC. We definitely > want to avoid that if possible for the first number/math object that has operator overloads. 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

« previous php.internals (#122832) next »