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

Reply via email to