ICU-13205 Prevent exception from being thrown when parsing numbers with very large exponents.

X-SVN-Rev: 40141
This commit is contained in:
Shane Carr 2017-05-26 23:59:13 +00:00
parent 6b9bbb9d9d
commit d0d0b173b4
2 changed files with 52 additions and 2 deletions

View file

@ -802,7 +802,7 @@ public class DecimalFormat extends NumberFormat {
Number result = Parse.parse(text, parsePosition, pprops, symbols);
// Backwards compatibility: return com.ibm.icu.math.BigDecimal
if (result instanceof java.math.BigDecimal) {
result = new com.ibm.icu.math.BigDecimal((java.math.BigDecimal) result);
result = safeConvertBigDecimal((java.math.BigDecimal) result);
}
return result;
}
@ -820,7 +820,7 @@ public class DecimalFormat extends NumberFormat {
Number number = result.getNumber();
// Backwards compatibility: return com.ibm.icu.math.BigDecimal
if (number instanceof java.math.BigDecimal) {
number = new com.ibm.icu.math.BigDecimal((java.math.BigDecimal) number);
number = safeConvertBigDecimal((java.math.BigDecimal) number);
result = new CurrencyAmount(number, result.getCurrency());
}
return result;
@ -2438,6 +2438,29 @@ public class DecimalFormat extends NumberFormat {
formatter.export(exportedProperties);
}
/**
* Converts a java.math.BigDecimal to a com.ibm.icu.math.BigDecimal with fallback for numbers
* outside of the range supported by com.ibm.icu.math.BigDecimal.
*
* @param number
* @return
*/
private Number safeConvertBigDecimal(java.math.BigDecimal number) {
try {
return new com.ibm.icu.math.BigDecimal(number);
} catch (NumberFormatException e) {
if (number.signum() > 0 && number.scale() < 0) {
return Double.POSITIVE_INFINITY;
} else if (number.scale() < 0) {
return Double.NEGATIVE_INFINITY;
} else if (number.signum() < 0) {
return -0.0;
} else {
return 0.0;
}
}
}
/**
* Updates the property bag with settings from the given pattern.
*

View file

@ -5284,6 +5284,33 @@ public class NumberFormatTest extends TestFmwk {
expect2(df, 35.0, "$35.0");
}
@Test
public void testParseVeryVeryLargeExponent() {
DecimalFormat df = new DecimalFormat();
ParsePosition ppos = new ParsePosition(0);
Object[][] cases = {
{"1.2E+1234567890", Double.POSITIVE_INFINITY},
{"1.2E+999999999", new com.ibm.icu.math.BigDecimal("1.2E+999999999")},
{"1.2E+1000000000", Double.POSITIVE_INFINITY},
{"-1.2E+999999999", new com.ibm.icu.math.BigDecimal("-1.2E+999999999")},
{"-1.2E+1000000000", Double.NEGATIVE_INFINITY},
{"1.2E-999999999", new com.ibm.icu.math.BigDecimal("1.2E-999999999")},
{"1.2E-1000000000", 0.0},
{"-1.2E-999999999", new com.ibm.icu.math.BigDecimal("-1.2E-999999999")},
{"-1.2E-1000000000", -0.0},
};
for (Object[] cas : cases) {
ppos.setIndex(0);
String input = (String) cas[0];
Number expected = (Number) cas[1];
Number actual = df.parse(input, ppos);
assertEquals(input, expected, actual);
}
}
@Test
public void testParseGroupingMode() {
ULocale[] locales = { // GROUPING DECIMAL