Hi Jordan, Lynn,

> 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.

> I'm inexperienced when it comes to maths and the precision here, but I do 
> have some experience when it comes to what the business I work for wants. 
> I've implemented BCMath in a couple of places where this kind of precision is 
> necessary, and I found that whenever I do divisions I prefer having at least 
> 2 extra digits. Would it make sense to internally always just store a more 
> accurate number? For things like additions/multiplications/subtractions it 
> could always use the highest precision, and then for divisions add like +3~6 
> or something. Whenever you have numbers that have a fraction like `10.5001` 
> it makes sense to set it to 4, but when you have `10` it suddenly becomes 0 
> when implicitly setting it. 
> 
> For the following examples assume each number is a BcNum:
> When doing something like `10 * 10.0000 * 10.000000000` I want the end result 
> to have a precision of at least 9 so I don't lose information. When I do 
> `((10 / 3) * 100) * 2` I don't want it to implicitly become 0, because the 
> precision here is important to me. I don't think using infinite precision 
> here is a reasonable approach either. I'm not sure what the correct answer 
> is, perhaps it's just "always manually set the precision"?

Thanks for the important perspective feedback.

One thing I overlooked: if the exponent of pow is negative, the scale of the 
result becomes unpredictable, just like with div.

e.g.
```
3 ** -1
= 0.333333.....
```

Also, an idea occurred to me while reading your comments.

The current assumption is that a Number always holds a single value. How if we 
made it so that it held two values? They are the numerator and the denominator.

This means that when we do division, no division is done internally, but we 
actually multiply the denominator. At the very end of the process, when 
converting to string, any reserved division is performed according to the 
specified scale.

If we have the option of not specifying a scale when converting to a string, it 
may be preferable to convert based on an implicit scale.

Regards.

Saki

Reply via email to