-
Notifications
You must be signed in to change notification settings - Fork 12
Description
I have a puzzle which has perplexed me.
Below, I list real-life use cases for how users want to round their numbers in Intl.NumberFormat. I am trying to figure out some set of options that is capable of expressing these various different rounding strategies.
Compact Notation Rounding
Input | Style 1 | Style 2 | Style 3 |
---|---|---|---|
1,234,000 | 1234K | 1234K | 1234K |
123,400 | 123K | 123K | 123K |
12,340 | 12K | 12K | 12.3K |
1,234 | 1.2K | 1.2K | 1.23K |
1,034 | 1K | 1.0K | 1.03K |
.1034 | .1 | .10 | .103 |
.1234 | .12 | .12 | .123 |
English Descriptions
- Style 1: When there are 2 or more digits before the decimal separator, round to the nearest integer. Otherwise, round to 2 significant digits. Strip trailing zeros.
- Style 2: When there are 2 or more digits before the decimal separator, round to the nearest integer. Otherwise, round to 2 significant digits. Retain trailing zeros.
- Style 3: When there are 3 or more digits before the decimal separator, round to the nearest integer. Otherwise, round to 3 significant digits. Strip trailing zeros.
Thoughts
Style 1 could be expressed as minFrac=0, maxFrac=0, and minSig=2, and when minSig is in conflict with maxFrac, minSig wins, except that we strip trailing zeros. In other words, we could make Style 1 be expressed as:
{
minimumFractionDigits: 0,
maximumFractionDigits: 0,
minimumSignificantDigits: 2
}
However, this approach is not capable of expressing Style 2.
We could have an option like "applyFractionGreaterThanIntDigits", which would mean to use minFrac/maxFrac when there are a certain number of integer digits, and minSig/maxSig when there are fewer. This is not a very pretty option, but it is capable of expressing all three styles:
Option | Style 1 | Style 2 | Style 3 |
---|---|---|---|
minimumFractionDigits | 0 | 0 | 0 |
maximumFractionDigits | 0 | 0 | 0 |
minimumSignificantDigits | 1 | 2 | 1 |
maximumSignificantDigits | 2 | 2 | 3 |
applyFractionGreaterThanIntDigits | 2 | 2 | 3 |
Currency Rounding
Input | Style 1 | Style 2 | Style 3 | Style 4 |
---|---|---|---|---|
1 | $1.00 | $1 | $1.00 | $1.00 |
1.01 | $1.01 | $1.01 | $1.00 | $1.00 |
1.04 | $1.04 | $1.04 | $1.05 | $1.00 |
1.12 | $1.12 | $1.12 | $1.10 | $1.10 |
English Descriptions
- Style 1: Round with 2 fixed fraction digits.
- Style 2: Round with 2 fixed fraction digits, but strip trailing zeros if the fraction is zero.
- Style 3: Nickel rounding: round to the nearest 0.05; display 2 fraction digits.
- Style 4: Dime rounding: round to the nearest 0.1; display 2 fraction digits.
Thoughts
A simple boolean option "stripFractionWhenEmpty" would solve Style 2.
A simple boolean option "nickelRounding" would solve Style 3.
About Trailing Zeros
Note that minFrac already serves absolutely no purpose other than retaining trailing zeros.
Given that minFrac is really only about retaining trailing zeros, for Style 4, we could let minFrac be greater than maxFrac, but it is weird for a minimum to be greater than a maximum.
Since a lot of the problems in this section, as well as Style 2 in the previous section, involve various different ways of treating trailing zeros, maybe we could introduce a "trailingZeroStyle" option, an enum with several different options that encompass all of the use cases.
Distance Rounding
Input | Style 1 | Style 2 |
---|---|---|
60 | 50 yards | 50 yards |
220 | 200 yards | 200 yards |
450 | 450 yards | 450 yards |
490 | 500 yards | 500 yards |
530 | 550 yards | 500 yards |
590 | 600 yards | 600 yards |
English Descriptions
- Style 1: Round to the nearest 50.
- Style 2: Round to the nearest 50 when below 500, and the nearest 100 when above 500.
Thoughts
Style 1 can be represented by a variant of nickelRounding. We could name the option nickelRoundingMagnitude, and if set, it would override fraction and significant rounding. Alternatively, we could allow minFrac/maxFrac to be less than zero, in which case they express the power of 10 at which you round.
Style 2 involves a cutoff. If we can't figure out how to support it, we could declare it out of scope.
Maybe we should throw the minFrac/maxFrac stuff out the door (keep it for backwards compatibility), and devise a whole new way of thinking about rounding strategies.