Please review this PR, which addresses a case where Decimal Format would 
violate certain RoundingMode contracts given the right pattern and double.

For example,


DecimalFormat df = new DecimalFormat();
df.setRoundingMode(RoundingMode.UP);
double small = 0.0001;
double big = 1.0001;
df.applyPattern("0.00");
df.format(small); // returns 0.00, which violates UP
df.format(big); // returns 1.01, which does not violate UP


In this example `0.0001` becomes `0.00`, a decrease in magnitude. This violates 
the RoundingMode.UP contract as RoundingMode.UP states "Note that this rounding 
mode never decreases the magnitude of the calculated value."

This edge case is a result of when values smaller than the absolute value of 
`.1` have more leading zeros between the decimal and the first non-zero digit 
(_0.0001 -> **3**_) than maximum fractional digits in the pattern (_0.00 -> 
**2**_).

The change to Decimal Format ensures that during this case, the rounding mode 
is considered before truncation, which dictates if the formatted number should 
insert a 1 in the least significant digit location.

The test validates the change by using data from larger counterparts. For 
example, If we are testing `0.0009`, we can format `1.0009` with the same 
pattern and mode that we use on `0.0009`, then compare the fractional portions 
to each other and ensure they are equal.

-------------

Commit messages:
 - Clarify test comment
 - Missing period
 - Add Impl
 - Use RoundingMode.values() instead of hard coding a static array
 - Add test

Changes: https://git.openjdk.org/jdk/pull/14110/files
 Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=14110&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8174722
  Stats: 164 lines in 2 files changed: 163 ins; 0 del; 1 mod
  Patch: https://git.openjdk.org/jdk/pull/14110.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/14110/head:pull/14110

PR: https://git.openjdk.org/jdk/pull/14110

Reply via email to