Fraction-Significant Rounding: Add a few more options
Description
relates to
Activity
Shane Carr March 1, 2021 at 7:53 AM
See the PR for the fix.
Shane Carr August 3, 2018 at 2:36 AM
Another way of looking at it is that Precision basically implements the following function.
Input: magnitude of most significant digit, # of significant digits
Output: rounding magnitude, display magnitude always, display magnitude if rounded
A very early version of my API had a lambda function. Maybe we could just re-introduce the lambda function again with this signature.
Shane Carr August 3, 2018 at 2:16 AM
So there are really two concepts at play here: the rounding magnitude and the display magnitude.
The three versions of withMinDigits all affect the rounding magnitude in the same way, and they are just three different ways of affecting the display magnitude.
The current version of withMaxDigits only affects the rounding magnitude. Maybe another version that also overrides display magnitude would be useful?
Or maybe make the trailing zeros a separate setting, either on the top level or on the Precision object?
Shane Carr July 17, 2018 at 11:22 PM
One more thought on withMinDigitsZeros(). A user might want to customize whether to show zeros only if digits existed but were "rounded off". For example, display 0.033 as 0.0 but 0 as just 0. This could go as two API methods, named something like:
withMinDigitsZerosAlways()
withMinDigitsZerosIfRounded()
These two would be instead of withMinDigitsZeros(). The existing method withMinDigits() would have the current behavior of not adding any trailing zeros.
Shane Carr July 17, 2018 at 11:16 PM
Here are APIs that could work maybe.
Strategy | 3.1 | 3.01 | 0.03333 | 32.1 | 65432 |
---|---|---|---|---|---|
integer() | 3 | 3 | 0 | 32 | 65432 |
integer().withMinDigits(2) | 3.1 | 3 | 0.033 | 32 | 65432 |
integer().withMinDigitsZeros(2) | 3.1 | 3.0 | 0.033 | 32 | 65432 |
integer().withMinDigits(2).withMaxDigits(3) | 3.1 | 3 | 0.033 | 32 | 65400 |
integer().withMinDigitsZeros(2).withMaxDigits(3) | 3.1 | 3.0 | 0.033 | 32 | 65400 |
maxSignificantDigits(3) | 3.1 | 3.01 | 0.0333 | 32.1 | 65400 |
maxSignificantDigits(3).withMaxFraction(1) | 3.1 | 3 | 0 | 32.1 | 65400 |
maxSignificantDigits(3).withMinDigitsZeros(2).withMaxFraction(1) | 3.1 | 3.0 | 0.0 | 32.1 | 65400 |
integer().withMinDigits(2).withMaxDigits(3).withMaxFraction(1) | 3.1 | 3 | 0 | 32 | 65400 |
integer().withMinDigitsZeros(2).withMaxDigits(3).withMaxFraction(1) | 3.1 | 3.0 | 0.0 | 32 | 65400 |
Basically, start at the left, then apply minima or maxima as you walk down the chain.
Only two API methods need to be added:
withMinDigitsZeros() – same as withMinDigits() but it adds trailing zeros.
withMaxFraction() – enforces a maximum number of digits after the decimal separator after other operations have been applied.
I'm still trying to puzzle through all of the possible combinations of fraction digits and significant digits that affect rounding. The FractionPrecision class handles some but not all of the cases.
Here are more possibilities for rounding strategies that we could add somehow:
Strategy
In ICU?
3.1
3.01
0.03333
32.1
65432
integer()
Y
3
3
0
32
65432
integer().withMinDigits(2)
Y
3.1
3
0.033
32
65432
?
N
3.1
3.0
0.033
32
65432
integer().withMinMaxDigits(2, 3)
N
3.1
3
0.033
32
65400
?
N
3.1
3.0
0.033
32
65400
maxSignificantDigits(3)
Y
3.1
3.01
0.0333
32.1
65400
maxSignificantDigits(3).withMaxFraction(1)
N
3.1
3
0
32.1
65400
minMaxSignificantDigits(2, 3).withMaxFraction(1)
N
3.1
3.0
0.0
32.1
65400
?
N
3.1
3
0
32
65400
?
N
3.1
3.0
0.0
32
65400
This came up with a Google team who appears to be interested in something that does not show as many digits in the big number (65432) but has expected behavior for small numbers.