ICU-10542 Add more tests. Use Math.log10() instead of multiplying by 0.1 in a for loop.
X-SVN-Rev: 34656
This commit is contained in:
parent
42dee8ca3b
commit
7db028c450
@ -892,13 +892,6 @@ public class DecimalFormat extends NumberFormat {
|
||||
// This is to fix rounding for scientific notation. See ticket:10542.
|
||||
// This code should go away when a permanent fix is done for ticket:9931.
|
||||
//
|
||||
// The problem:
|
||||
// DigitList does ROUND_HALF_EVEN only if the number of digits in the number exceeds the precision.
|
||||
// Therefore if rounding mode is set to anything besides ROUND_HALF_EVEN, the results will be incorrect.
|
||||
// The {@link #resetActualRounding} method addresses this problem, but its solution only works for fixed
|
||||
// decimal numbers.
|
||||
//
|
||||
// The solution:
|
||||
// This block of code only executes for scientific notation so it will not interfere with the
|
||||
// previous fix in {@link #resetActualRounding} for fixed decimal numbers.
|
||||
// Moreover this code only runs when there is rounding to be done (precision > 0) and when the
|
||||
@ -907,21 +900,16 @@ public class DecimalFormat extends NumberFormat {
|
||||
// the number of digits indicated by precision. In this way, we avoid using the default
|
||||
// ROUND_HALF_EVEN behavior of DigitList. For example, if number = 0.003016 and roundingMode =
|
||||
// ROUND_DOWN and precision = 3 then after this code executes, number = 0.00301 (3 significant digits)
|
||||
if (useExponentialNotation && precision > 0 && roundingMode != BigDecimal.ROUND_HALF_EVEN) {
|
||||
double adjNumber = number;
|
||||
for (int i = 1; i < precision; i++) {
|
||||
adjNumber *= 0.1;
|
||||
}
|
||||
double roundingInc = 1.0;
|
||||
double roundingIncReciprocal = 1.0;
|
||||
while (adjNumber < 1.0) {
|
||||
roundingIncReciprocal *= 10;
|
||||
adjNumber *= 10;
|
||||
}
|
||||
while (adjNumber >= 10.0) {
|
||||
roundingInc *= 10;
|
||||
roundingIncReciprocal = 0.0;
|
||||
adjNumber *= 0.1;
|
||||
if (useExponentialNotation && precision > 0 && number != 0.0 && roundingMode != BigDecimal.ROUND_HALF_EVEN) {
|
||||
int log10RoundingIncr = 1 - precision + (int) Math.floor(Math.log10(Math.abs(number)));
|
||||
double roundingIncReciprocal = 0.0;
|
||||
double roundingInc = 0.0;
|
||||
if (log10RoundingIncr < 0) {
|
||||
roundingIncReciprocal =
|
||||
BigDecimal.ONE.movePointRight(-log10RoundingIncr).doubleValue();
|
||||
} else {
|
||||
roundingInc =
|
||||
BigDecimal.ONE.movePointRight(log10RoundingIncr).doubleValue();
|
||||
}
|
||||
number = DecimalFormat.round(number, roundingInc, roundingIncReciprocal, roundingMode, isNegative);
|
||||
}
|
||||
|
@ -86,6 +86,61 @@ public class NumberFormatTest extends com.ibm.icu.dev.test.TestFmwk {
|
||||
{"-3.01E3", "-3.01E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3"},
|
||||
{"-3.01E3", "-3.01E3", "-3.01E3", "3.02E3", "3.02E3", "3.02E3"}};
|
||||
verifyRounding(format, values, expected, roundingModes, descriptions);
|
||||
values = new double[]{0.0, -0.0};
|
||||
// The order of these expected values correspond to the order of roundingModes and the order of values.
|
||||
expected = new String[][]{
|
||||
{"0.00E0", "-0.00E0"},
|
||||
{"0.00E0", "-0.00E0"},
|
||||
{"0.00E0", "-0.00E0"},
|
||||
{"0.00E0", "-0.00E0"},
|
||||
{"0.00E0", "-0.00E0"},
|
||||
{"0.00E0", "-0.00E0"},
|
||||
{"0.00E0", "-0.00E0"}};
|
||||
verifyRounding(format, values, expected, roundingModes, descriptions);
|
||||
values = new double[]{1e25, 1e25 + 1e15, 1e25 - 1e15};
|
||||
// The order of these expected values correspond to the order of roundingModes and the order of values.
|
||||
expected = new String[][]{
|
||||
{"1.00E25", "1.01E25", "1.00E25"},
|
||||
{"1.00E25", "1.00E25", "9.99E24"},
|
||||
{"1.00E25", "1.00E25", "9.99E24"},
|
||||
{"1.00E25", "1.00E25", "1.00E25"},
|
||||
{"1.00E25", "1.00E25", "1.00E25"},
|
||||
{"1.00E25", "1.00E25", "1.00E25"},
|
||||
{"1.00E25", "1.01E25", "1.00E25"}};
|
||||
verifyRounding(format, values, expected, roundingModes, descriptions);
|
||||
values = new double[]{-1e25, -1e25 + 1e15, -1e25 - 1e15};
|
||||
// The order of these expected values correspond to the order of roundingModes and the order of values.
|
||||
expected = new String[][]{
|
||||
{"-1.00E25", "-9.99E24", "-1.00E25"},
|
||||
{"-1.00E25", "-9.99E24", "-1.00E25"},
|
||||
{"-1.00E25", "-1.00E25", "-1.01E25"},
|
||||
{"-1.00E25", "-1.00E25", "-1.00E25"},
|
||||
{"-1.00E25", "-1.00E25", "-1.00E25"},
|
||||
{"-1.00E25", "-1.00E25", "-1.00E25"},
|
||||
{"-1.00E25", "-1.00E25", "-1.01E25"}};
|
||||
verifyRounding(format, values, expected, roundingModes, descriptions);
|
||||
values = new double[]{1e-25, 1e-25 + 1e-35, 1e-25 - 1e-35};
|
||||
// The order of these expected values correspond to the order of roundingModes and the order of values.
|
||||
expected = new String[][]{
|
||||
{"1.00E-25", "1.01E-25", "1.00E-25"},
|
||||
{"1.00E-25", "1.00E-25", "9.99E-26"},
|
||||
{"1.00E-25", "1.00E-25", "9.99E-26"},
|
||||
{"1.00E-25", "1.00E-25", "1.00E-25"},
|
||||
{"1.00E-25", "1.00E-25", "1.00E-25"},
|
||||
{"1.00E-25", "1.00E-25", "1.00E-25"},
|
||||
{"1.00E-25", "1.01E-25", "1.00E-25"}};
|
||||
verifyRounding(format, values, expected, roundingModes, descriptions);
|
||||
values = new double[]{-1e-25, -1e-25 + 1e-35, -1e-25 - 1e-35};
|
||||
// The order of these expected values correspond to the order of roundingModes and the order of values.
|
||||
expected = new String[][]{
|
||||
{"-1.00E-25", "-9.99E-26", "-1.00E-25"},
|
||||
{"-1.00E-25", "-9.99E-26", "-1.00E-25"},
|
||||
{"-1.00E-25", "-1.00E-25", "-1.01E-25"},
|
||||
{"-1.00E-25", "-1.00E-25", "-1.00E-25"},
|
||||
{"-1.00E-25", "-1.00E-25", "-1.00E-25"},
|
||||
{"-1.00E-25", "-1.00E-25", "-1.00E-25"},
|
||||
{"-1.00E-25", "-1.00E-25", "-1.01E-25"}};
|
||||
verifyRounding(format, values, expected, roundingModes, descriptions);
|
||||
}
|
||||
|
||||
private void verifyRounding(DecimalFormat format, double[] values, String[][] expected, int[] roundingModes,
|
||||
|
Loading…
Reference in New Issue
Block a user