From b655a9fa24bad53bff74e9669d6acd27981e80ad Mon Sep 17 00:00:00 2001 From: aryanraj45 Date: Fri, 13 Feb 2026 03:19:15 +0530 Subject: [PATCH] ICU-22872 Fix BigDecimal scale in DecimalFormat.parse() --- .../icu/dev/test/format/NumberFormatTest.java | 37 +++++++++++++++++++ .../number/DecimalQuantity_AbstractBCD.java | 8 +++- .../icu/impl/number/parse/DecimalMatcher.java | 1 + 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/icu4j/main/common_tests/src/test/java/com/ibm/icu/dev/test/format/NumberFormatTest.java b/icu4j/main/common_tests/src/test/java/com/ibm/icu/dev/test/format/NumberFormatTest.java index 406efb4935fc..dd1dab2a7409 100644 --- a/icu4j/main/common_tests/src/test/java/com/ibm/icu/dev/test/format/NumberFormatTest.java +++ b/icu4j/main/common_tests/src/test/java/com/ibm/icu/dev/test/format/NumberFormatTest.java @@ -8677,4 +8677,41 @@ 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")); + } } diff --git a/icu4j/main/core/src/main/java/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java b/icu4j/main/core/src/main/java/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java index 407062af2803..0d22f6383208 100644 --- a/icu4j/main/core/src/main/java/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java +++ b/icu4j/main/core/src/main/java/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java @@ -710,7 +710,13 @@ public BigDecimal toBigDecimal() { // Converting to a BigDecimal requires Double.toString(). convertToAccurateDouble(); } - return bcdToBigDecimal(); + BigDecimal result = bcdToBigDecimal(); + // Preserve trailing zeros recorded by setMinFraction + int minScale = -getLowerDisplayMagnitude(); + if (minScale > result.scale()) { + result = result.setScale(minScale); + } + return result; } private static int safeSubtract(int a, int b) { diff --git a/icu4j/main/core/src/main/java/com/ibm/icu/impl/number/parse/DecimalMatcher.java b/icu4j/main/core/src/main/java/com/ibm/icu/impl/number/parse/DecimalMatcher.java index f3dd2a7a12aa..cf45b0443e8a 100644 --- a/icu4j/main/core/src/main/java/com/ibm/icu/impl/number/parse/DecimalMatcher.java +++ b/icu4j/main/core/src/main/java/com/ibm/icu/impl/number/parse/DecimalMatcher.java @@ -395,6 +395,7 @@ public boolean match(StringSegment segment, ParsedNumber result, int exponentSig // Adjust for fraction part. digitsConsumed.adjustMagnitude(-digitsAfterDecimalPlace); + digitsConsumed.setMinFraction(digitsAfterDecimalPlace); // Set the digits, either normal or exponent. if (exponentSign != 0 && segment.getOffset() != initialOffset) {