From 8d8f846755dc9dccdf5f2d8ab115d53137d56c0e Mon Sep 17 00:00:00 2001 From: Shane Carr Date: Fri, 30 Mar 2018 08:21:06 +0000 Subject: [PATCH] ICU-13634 Fixing significant digit display on zero when minInt is zero. X-SVN-Rev: 41178 --- icu4c/source/i18n/number_decimalquantity.cpp | 6 ++++++ icu4c/source/i18n/number_rounding.cpp | 4 ++++ icu4c/source/test/intltest/numbertest_api.cpp | 18 ++++++++++++++++++ .../number/DecimalQuantity_AbstractBCD.java | 6 ++++++ .../core/src/com/ibm/icu/number/Rounder.java | 4 ++++ .../test/number/NumberFormatterApiTest.java | 16 ++++++++++++++++ 6 files changed, 54 insertions(+) diff --git a/icu4c/source/i18n/number_decimalquantity.cpp b/icu4c/source/i18n/number_decimalquantity.cpp index a63044f9812..bb731938f12 100644 --- a/icu4c/source/i18n/number_decimalquantity.cpp +++ b/icu4c/source/i18n/number_decimalquantity.cpp @@ -149,6 +149,12 @@ void DecimalQuantity::setIntegerLength(int32_t minInt, int32_t maxInt) { U_ASSERT(minInt >= 0); U_ASSERT(maxInt >= minInt); + // Special behavior: do not set minInt to be less than what is already set. + // This is so significant digits rounding can set the integer length. + if (minInt < lReqPos) { + minInt = lReqPos; + } + // Save values into internal state // Negation is safe for minFrac/maxFrac because -Integer.MAX_VALUE > Integer.MIN_VALUE lOptPos = maxInt; diff --git a/icu4c/source/i18n/number_rounding.cpp b/icu4c/source/i18n/number_rounding.cpp index 80120261e1c..b5e37194f8d 100644 --- a/icu4c/source/i18n/number_rounding.cpp +++ b/icu4c/source/i18n/number_rounding.cpp @@ -342,6 +342,10 @@ void Rounder::apply(impl::DecimalQuantity &value, UErrorCode& status) const { value.setFractionLength( uprv_max(0, -getDisplayMagnitudeSignificant(value, fUnion.fracSig.fMinSig)), INT32_MAX); + // Make sure that digits are displayed on zero. + if (value.isZero() && fUnion.fracSig.fMinSig > 0) { + value.setIntegerLength(1, INT32_MAX); + } break; case RND_FRACTION_SIGNIFICANT: { diff --git a/icu4c/source/test/intltest/numbertest_api.cpp b/icu4c/source/test/intltest/numbertest_api.cpp index 9fe790cd4a6..a6d1a3553c6 100644 --- a/icu4c/source/test/intltest/numbertest_api.cpp +++ b/icu4c/source/test/intltest/numbertest_api.cpp @@ -910,6 +910,24 @@ void NumberFormatterApiTest::roundingFigures() { Locale::getEnglish(), 9.99999, u"10.0"); + + assertFormatSingle( + u"Fixed Significant on zero with lots of integer width", + u"@ integer-width/+000", + NumberFormatter::with().rounding(Rounder::fixedDigits(1)) + .integerWidth(IntegerWidth::zeroFillTo(3)), + Locale::getEnglish(), + 0, + "000"); + + assertFormatSingle( + u"Fixed Significant on zero with zero integer width", + u"@ integer-width/+", + NumberFormatter::with().rounding(Rounder::fixedDigits(1)) + .integerWidth(IntegerWidth::zeroFillTo(0)), + Locale::getEnglish(), + 0, + "0"); } void NumberFormatterApiTest::roundingFractionFigures() { diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java index b5afb37e2e6..d513ef3c160 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java @@ -142,6 +142,12 @@ public abstract class DecimalQuantity_AbstractBCD implements DecimalQuantity { assert minInt >= 0; assert maxInt >= minInt; + // Special behavior: do not set minInt to be less than what is already set. + // This is so significant digits rounding can set the integer length. + if (minInt < lReqPos) { + minInt = lReqPos; + } + // Save values into internal state // Negation is safe for minFrac/maxFrac because -Integer.MAX_VALUE > Integer.MIN_VALUE lOptPos = maxInt; diff --git a/icu4j/main/classes/core/src/com/ibm/icu/number/Rounder.java b/icu4j/main/classes/core/src/com/ibm/icu/number/Rounder.java index 9cec17b8af6..47b6df70843 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/number/Rounder.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/number/Rounder.java @@ -609,6 +609,10 @@ public abstract class Rounder implements Cloneable { value.roundToMagnitude(getRoundingMagnitudeSignificant(value, maxSig), mathContext); value.setFractionLength(Math.max(0, -getDisplayMagnitudeSignificant(value, minSig)), Integer.MAX_VALUE); + // Make sure that digits are displayed on zero. + if (value.isZero() && minSig > 0) { + value.setIntegerLength(1, Integer.MAX_VALUE); + } } /** diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java index fad64604d95..b9ca3976f30 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java @@ -894,6 +894,22 @@ public class NumberFormatterApiTest { ULocale.ENGLISH, 9.99999, "10.0"); + + assertFormatSingle( + "Fixed Significant on zero with zero integer width", + "@ integer-width/+", + NumberFormatter.with().rounding(Rounder.fixedDigits(1)).integerWidth(IntegerWidth.zeroFillTo(0)), + ULocale.ENGLISH, + 0, + "0"); + + assertFormatSingle( + "Fixed Significant on zero with lots of integer width", + "@ integer-width/+000", + NumberFormatter.with().rounding(Rounder.fixedDigits(1)).integerWidth(IntegerWidth.zeroFillTo(3)), + ULocale.ENGLISH, + 0, + "000"); } @Test -- 2.40.0