Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8677,4 +8677,42 @@ public void testStrictParse() throws java.text.ParseException {
}
}
}

/**
* Test that BigDecimal scale is correctly preserved when parsing numbers with trailing zeros.
* This is a regression test for ICU-22872.
*/
@Test
public void TestParseBigDecimalScale() throws ParseException {
DecimalFormat df = new DecimalFormat("0.00");
df.setParseBigDecimal(true);

// Test cases: input string, expected scale
Object[][] testCases = {
{"0.0", 1},
{"1.0", 1},
{"1.00", 2},
{"1.10", 2},
{"0.10", 2},
{"123.450", 3},
{"5.0000", 4},
};

for (Object[] testCase : testCases) {
String input = (String) testCase[0];
int expectedScale = (Integer) testCase[1];
Number result = df.parse(input);
assertTrue("Result should be BigDecimal for input: " + input, result instanceof BigDecimal);
BigDecimal bd = (BigDecimal) result;
assertEquals("Scale mismatch for input: " + input, expectedScale, bd.scale());
}

// Verify values are correct, not just scales
assertEquals("Value check for 0.0",
new BigDecimal("0.0"), df.parse("0.0"));
assertEquals("Value check for 1.00",
new BigDecimal("1.00"), df.parse("1.00"));
assertEquals("Value check for 123.450",
new BigDecimal("123.450"), df.parse("123.450"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ public boolean match(StringSegment segment, ParsedNumber result, int exponentSig
// Set other information into the result and return.
if (actualDecimalString != null) {
result.flags |= ParsedNumber.FLAG_HAS_DECIMAL_SEPARATOR;
result.fractionDigitCount = digitsAfterDecimalPlace;
}
result.setCharsConsumed(segment);
return segment.length() == 0 || maybeMore;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ public class ParsedNumber {
/** The currency that got consumed. */
public String currencyCode;

/**
* The number of digits after the decimal separator, including trailing zeros.
* Used to preserve scale when parsing BigDecimals.
* A value of -1 means no decimal separator was seen.
*/
public int fractionDigitCount;

public static final int FLAG_NEGATIVE = 0x0001;
public static final int FLAG_PERCENT = 0x0002;
public static final int FLAG_PERMILLE = 0x0004;
Expand Down Expand Up @@ -67,6 +74,7 @@ public void clear() {
prefix = null;
suffix = null;
currencyCode = null;
fractionDigitCount = -1;
}

public void copyFrom(ParsedNumber other) {
Expand All @@ -79,6 +87,7 @@ public void copyFrom(ParsedNumber other) {
prefix = other.prefix;
suffix = other.suffix;
currencyCode = other.currencyCode;
fractionDigitCount = other.fractionDigitCount;
}

/**
Expand Down Expand Up @@ -128,6 +137,7 @@ public Number getNumber() {
public Number getNumber(int parseFlags) {
boolean sawNaN = 0 != (flags & FLAG_NAN);
boolean sawInfinity = 0 != (flags & FLAG_INFINITY);
boolean sawExponent = 0 != (flags & FLAG_HAS_EXPONENT);
boolean forceBigDecimal = 0 != (parseFlags & ParsingUtils.PARSE_FLAG_FORCE_BIG_DECIMAL);
boolean integerOnly = 0 != (parseFlags & ParsingUtils.PARSE_FLAG_INTEGER_ONLY);

Expand All @@ -150,7 +160,13 @@ public Number getNumber(int parseFlags) {
if (quantity.fitsInLong() && !forceBigDecimal) {
return quantity.toLong(false);
} else {
return quantity.toBigDecimal();
java.math.BigDecimal result = quantity.toBigDecimal();
// Preserve trailing zeros by adjusting scale based on fractionDigitCount
// Only do this when no exponent was seen (exponent changes the scale)
if (!sawExponent && fractionDigitCount >= 0 && result.scale() < fractionDigitCount) {
result = result.setScale(fractionDigitCount);
}
return result;
}
}

Expand Down