ICU-11808 Missing ArithmeticException when using ICU4J DecimalFormat
X-SVN-Rev: 37909
This commit is contained in:
parent
1af9647af1
commit
1a6b2975d1
@ -1123,6 +1123,10 @@ public class DecimalFormat extends NumberFormat {
|
||||
number *= multiplier;
|
||||
synchronized (digitList) {
|
||||
digitList.set(number, precision(true));
|
||||
// Issue 11808
|
||||
if (digitList.wasRounded() && roundingMode == BigDecimal.ROUND_UNNECESSARY) {
|
||||
throw new ArithmeticException("Rounding necessary");
|
||||
}
|
||||
return subformat(number, result, fieldPosition, isNegative, true, parseAttr);
|
||||
}
|
||||
}
|
||||
@ -1154,6 +1158,10 @@ public class DecimalFormat extends NumberFormat {
|
||||
// number.
|
||||
synchronized (digitList) {
|
||||
digitList.set(number, precision(true));
|
||||
// For issue 11808.
|
||||
if (digitList.wasRounded() && roundingMode == BigDecimal.ROUND_UNNECESSARY) {
|
||||
throw new ArithmeticException("Rounding necessary");
|
||||
}
|
||||
return subformat(number.intValue(), result, fieldPosition, number.signum() < 0, true,
|
||||
parseAttr);
|
||||
}
|
||||
@ -1184,6 +1192,10 @@ public class DecimalFormat extends NumberFormat {
|
||||
synchronized (digitList) {
|
||||
digitList.set(number, precision(false), !useExponentialNotation &&
|
||||
!areSignificantDigitsUsed());
|
||||
// For issue 11808.
|
||||
if (digitList.wasRounded() && roundingMode == BigDecimal.ROUND_UNNECESSARY) {
|
||||
throw new ArithmeticException("Rounding necessary");
|
||||
}
|
||||
return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0,
|
||||
false, parseAttr);
|
||||
}
|
||||
@ -1213,6 +1225,10 @@ public class DecimalFormat extends NumberFormat {
|
||||
synchronized (digitList) {
|
||||
digitList.set(number, precision(false), !useExponentialNotation &&
|
||||
!areSignificantDigitsUsed());
|
||||
// For issue 11808.
|
||||
if (digitList.wasRounded() && roundingMode == BigDecimal.ROUND_UNNECESSARY) {
|
||||
throw new ArithmeticException("Rounding necessary");
|
||||
}
|
||||
return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0,
|
||||
false, false);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1996-2011, International Business Machines Corporation and *
|
||||
* Copyright (C) 1996-2015, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
@ -411,6 +411,8 @@ final class DigitList {
|
||||
// DDDDDE+/-DDDDD.
|
||||
String rep = Double.toString(source);
|
||||
|
||||
didRound = false;
|
||||
|
||||
set(rep, MAX_LONG_DIGITS);
|
||||
|
||||
if (fixedPoint) {
|
||||
@ -552,10 +554,12 @@ final class DigitList {
|
||||
digits[0] = (byte) '1';
|
||||
++decimalAt;
|
||||
maximumDigits = 0; // Adjust the count
|
||||
didRound = true;
|
||||
break;
|
||||
}
|
||||
|
||||
++digits[maximumDigits];
|
||||
didRound = true;
|
||||
if (digits[maximumDigits] <= '9') break;
|
||||
// digits[maximumDigits] = '0'; // Unnecessary since we'll truncate this
|
||||
}
|
||||
@ -571,6 +575,18 @@ final class DigitList {
|
||||
}
|
||||
}
|
||||
|
||||
// Value to indicate that rounding was done.
|
||||
private boolean didRound = false;
|
||||
|
||||
/**
|
||||
* Indicates if last digit set was rounded or not.
|
||||
* true indicates it was rounded.
|
||||
* false indicates rounding has not been done.
|
||||
*/
|
||||
public boolean wasRounded() {
|
||||
return didRound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility routine to set the value of the digit list from a long
|
||||
*/
|
||||
@ -596,6 +612,8 @@ final class DigitList {
|
||||
// which is outside the legal range of a long, but which can
|
||||
// be represented by DigitList.
|
||||
// [NEW] Faster implementation
|
||||
didRound = false;
|
||||
|
||||
if (source <= 0) {
|
||||
if (source == Long.MIN_VALUE) {
|
||||
decimalAt = count = MAX_LONG_DIGITS;
|
||||
@ -634,7 +652,8 @@ final class DigitList {
|
||||
String stringDigits = source.toString();
|
||||
|
||||
count = decimalAt = stringDigits.length();
|
||||
|
||||
didRound = false;
|
||||
|
||||
// Don't copy trailing zeros
|
||||
while (count > 1 && stringDigits.charAt(count - 1) == '0') --count;
|
||||
|
||||
@ -715,6 +734,8 @@ final class DigitList {
|
||||
//| }
|
||||
//| }
|
||||
|
||||
didRound = false;
|
||||
|
||||
// The maxDigits here could also be Integer.MAX_VALUE
|
||||
set(stringDigits, stringDigits.length());
|
||||
|
||||
|
@ -4256,4 +4256,46 @@ public class NumberFormatTest extends com.ibm.icu.dev.test.TestFmwk {
|
||||
new NumberFormatTestTuple().toString();
|
||||
}
|
||||
|
||||
// Testing for Issue 11808.
|
||||
public void TestRoundUnnecessarytIssue11808 () {
|
||||
DecimalFormat df = (DecimalFormat) DecimalFormat.getInstance();
|
||||
StringBuffer result = new StringBuffer("");
|
||||
df.setRoundingMode(BigDecimal.ROUND_UNNECESSARY);
|
||||
df.applyPattern("00.0#E0");
|
||||
|
||||
try {
|
||||
df.format(99999.0, result, new FieldPosition(0));
|
||||
fail("Missing ArithmeticException for double: " + result);
|
||||
} catch (ArithmeticException expected) {
|
||||
// The exception should be thrown, since rounding is needed.
|
||||
}
|
||||
|
||||
try {
|
||||
result = df.format(99999, result, new FieldPosition(0));
|
||||
fail("Missing ArithmeticException for int: " + result);
|
||||
} catch (ArithmeticException expected) {
|
||||
// The exception should be thrown, since rounding is needed.
|
||||
}
|
||||
|
||||
try {
|
||||
result = df.format(new BigInteger("999999"), result, new FieldPosition(0));
|
||||
fail("Missing ArithmeticException for BigInteger: " + result);
|
||||
} catch (ArithmeticException expected) {
|
||||
// The exception should be thrown, since rounding is needed.
|
||||
}
|
||||
|
||||
try {
|
||||
result = df.format(new BigDecimal("99999"), result, new FieldPosition(0));
|
||||
fail("Missing ArithmeticException for BigDecimal: " + result);
|
||||
} catch (ArithmeticException expected) {
|
||||
// The exception should be thrown, since rounding is needed.
|
||||
}
|
||||
|
||||
try {
|
||||
result = df.format(new BigDecimal("-99999"), result, new FieldPosition(0));
|
||||
fail("Missing ArithmeticException for BigDecimal: " + result);
|
||||
} catch (ArithmeticException expected) {
|
||||
// The exception should be thrown, since rounding is needed.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user