*this,
minSignificantDigits,
maxSignificantDigits,
- priority);
+ priority,
+ false);
} else {
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
*this,
1,
minSignificantDigits,
- UNUM_ROUNDING_PRIORITY_RELAXED);
+ UNUM_ROUNDING_PRIORITY_RELAXED,
+ true);
} else {
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
return constructFractionSignificant(*this,
1,
maxSignificantDigits,
- UNUM_ROUNDING_PRIORITY_STRICT);
+ UNUM_ROUNDING_PRIORITY_STRICT,
+ true);
} else {
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
const FractionPrecision &base,
int32_t minSig,
int32_t maxSig,
- UNumberRoundingPriority priority) {
+ UNumberRoundingPriority priority,
+ bool retain) {
FractionSignificantSettings settings = base.fUnion.fracSig;
settings.fMinSig = static_cast<digits_t>(minSig);
settings.fMaxSig = static_cast<digits_t>(maxSig);
settings.fPriority = priority;
+ settings.fRetain = retain;
PrecisionUnion union_;
union_.fracSig = settings;
return {RND_FRACTION_SIGNIFICANT, union_};
break;
case Precision::RND_FRACTION_SIGNIFICANT: {
+ // From ECMA-402:
+ /*
+ Let sResult be ToRawPrecision(...).
+ Let fResult be ToRawFixed(...).
+ If intlObj.[[RoundingType]] is morePrecision, then
+ If sResult.[[RoundingMagnitude]] ≤ fResult.[[RoundingMagnitude]], then
+ Let result be sResult.
+ Else,
+ Let result be fResult.
+ Else,
+ Assert: intlObj.[[RoundingType]] is lessPrecision.
+ If sResult.[[RoundingMagnitude]] ≤ fResult.[[RoundingMagnitude]], then
+ Let result be fResult.
+ Else,
+ Let result be sResult.
+ */
+
int32_t roundingMag1 = getRoundingMagnitudeFraction(fPrecision.fUnion.fracSig.fMaxFrac);
int32_t roundingMag2 = getRoundingMagnitudeSignificant(value, fPrecision.fUnion.fracSig.fMaxSig);
int32_t roundingMag;
} else {
roundingMag = uprv_max(roundingMag1, roundingMag2);
}
- value.roundToMagnitude(roundingMag, fRoundingMode, status);
+ if (!value.isZeroish()) {
+ int32_t upperMag = value.getMagnitude();
+ value.roundToMagnitude(roundingMag, fRoundingMode, status);
+ if (!value.isZeroish() && value.getMagnitude() != upperMag && roundingMag1 == roundingMag2) {
+ // roundingMag2 needs to be the magnitude after rounding
+ roundingMag2 += 1;
+ }
+ }
int32_t displayMag1 = getDisplayMagnitudeFraction(fPrecision.fUnion.fracSig.fMinFrac);
int32_t displayMag2 = getDisplayMagnitudeSignificant(value, fPrecision.fUnion.fracSig.fMinSig);
- int32_t displayMag = uprv_min(displayMag1, displayMag2);
+ int32_t displayMag;
+ if (fPrecision.fUnion.fracSig.fRetain) {
+ // withMinDigits + withMaxDigits
+ displayMag = uprv_min(displayMag1, displayMag2);
+ } else if (fPrecision.fUnion.fracSig.fPriority == UNUM_ROUNDING_PRIORITY_RELAXED) {
+ if (roundingMag2 <= roundingMag1) {
+ displayMag = displayMag2;
+ } else {
+ displayMag = displayMag1;
+ }
+ } else {
+ U_ASSERT(fPrecision.fUnion.fracSig.fPriority == UNUM_ROUNDING_PRIORITY_STRICT);
+ if (roundingMag2 <= roundingMag1) {
+ displayMag = displayMag1;
+ } else {
+ displayMag = displayMag2;
+ }
+ }
resolvedMinFraction = uprv_max(0, -displayMag);
break;
// @, @@, @@@
maxSig = minSig;
}
- UNumberRoundingPriority priority;
+ auto& oldPrecision = static_cast<const FractionPrecision&>(macros.precision);
if (offset < segment.length()) {
+ UNumberRoundingPriority priority;
if (maxSig == -1) {
// The wildcard character is not allowed with the priority annotation
status = U_NUMBER_SKELETON_SYNTAX_ERROR;
status = U_NUMBER_SKELETON_SYNTAX_ERROR;
return false;
}
+ macros.precision = oldPrecision.withSignificantDigits(minSig, maxSig, priority);
} else if (maxSig == -1) {
// withMinDigits
- maxSig = minSig;
- minSig = 1;
- priority = UNUM_ROUNDING_PRIORITY_RELAXED;
+ macros.precision = oldPrecision.withMinDigits(minSig);
} else if (minSig == 1) {
// withMaxDigits
- priority = UNUM_ROUNDING_PRIORITY_STRICT;
+ macros.precision = oldPrecision.withMaxDigits(maxSig);
} else {
// Digits options with both min and max sig require the priority option
status = U_NUMBER_SKELETON_SYNTAX_ERROR;
return false;
}
- auto& oldPrecision = static_cast<const FractionPrecision&>(macros.precision);
- macros.precision = oldPrecision.withSignificantDigits(minSig, maxSig, priority);
return true;
}
const Precision::FractionSignificantSettings& impl = macros.precision.fUnion.fracSig;
blueprint_helpers::generateFractionStem(impl.fMinFrac, impl.fMaxFrac, sb, status);
sb.append(u'/');
- blueprint_helpers::generateDigitsStem(impl.fMinSig, impl.fMaxSig, sb, status);
- if (impl.fPriority == UNUM_ROUNDING_PRIORITY_RELAXED) {
- sb.append(u'r');
+ if (impl.fRetain) {
+ if (impl.fPriority == UNUM_ROUNDING_PRIORITY_RELAXED) {
+ // withMinDigits
+ blueprint_helpers::generateDigitsStem(impl.fMaxSig, -1, sb, status);
+ } else {
+ // withMaxDigits
+ blueprint_helpers::generateDigitsStem(1, impl.fMaxSig, sb, status);
+ }
} else {
- sb.append(u's');
+ blueprint_helpers::generateDigitsStem(impl.fMinSig, impl.fMaxSig, sb, status);
+ if (impl.fPriority == UNUM_ROUNDING_PRIORITY_RELAXED) {
+ sb.append(u'r');
+ } else {
+ sb.append(u's');
+ }
}
} else if (macros.precision.fType == Precision::RND_INCREMENT
|| macros.precision.fType == Precision::RND_INCREMENT_ONE
impl::digits_t fMaxSig;
/** @internal (private) */
UNumberRoundingPriority fPriority;
+ /**
+ * Whether to retain trailing zeros based on the looser strategy.
+ * @internal (private)
+ */
+ bool fRetain;
} fracSig;
/** @internal (private) */
struct IncrementSettings {
const FractionPrecision &base,
int32_t minSig,
int32_t maxSig,
- UNumberRoundingPriority priority);
+ UNumberRoundingPriority priority,
+ bool retain);
static IncrementPrecision constructIncrement(double increment, int32_t minFrac);
void roundingFractionFigures();
void roundingOther();
void roundingIncrementRegressionTest();
+ void roundingPriorityCoverageTest();
void grouping();
void padding();
void integerWidth();
TESTCASE_AUTO(roundingFractionFigures);
TESTCASE_AUTO(roundingOther);
TESTCASE_AUTO(roundingIncrementRegressionTest);
+ TESTCASE_AUTO(roundingPriorityCoverageTest);
TESTCASE_AUTO(grouping);
TESTCASE_AUTO(padding);
TESTCASE_AUTO(integerWidth);
-98.7654321,
u"-98.8");
+ assertFormatSingle(
+ u"Fixed Significant at rounding boundary",
+ u"@@@",
+ u"@@@",
+ NumberFormatter::with().precision(Precision::fixedSignificantDigits(3)),
+ Locale::getEnglish(),
+ 9.999,
+ u"10.0");
+
assertFormatSingle(
u"Fixed Significant Zero",
u"@@@",
assertFormatDescending(
u"FracSig withSignificantDigits STRICT",
u"precision-integer/@#s",
- u"./@#",
+ u"./@#s",
NumberFormatter::with().precision(Precision::maxFraction(0)
.withSignificantDigits(1, 2, UNUM_ROUNDING_PRIORITY_STRICT)),
Locale::getEnglish(),
1,
u"1.00");
- // Trailing zeros are always retained:
+ // Trailing zeros follow the strategy that was chosen:
assertFormatSingle(
u"FracSig withSignificantDigits Trailing Zeros STRICT",
u".0/@@@s",
.withSignificantDigits(3, 3, UNUM_ROUNDING_PRIORITY_STRICT)),
Locale::getEnglish(),
1,
- u"1.00");
+ u"1.0");
assertFormatSingle(
u"FracSig withSignificantDigits at rounding boundary",
.withSignificantDigits(3, 3, UNUM_ROUNDING_PRIORITY_STRICT)),
Locale::getEnglish(),
9.99,
- u"10.0");
+ u"10");
assertFormatSingle(
u"FracSig with Trailing Zero Display",
assertEquals("ICU-21668", u"5,000", increment);
}
+void NumberFormatterApiTest::roundingPriorityCoverageTest() {
+ IcuTestErrorCode status(*this, "roundingPriorityCoverageTest");
+ struct TestCase {
+ double input;
+ const char16_t* expectedRelaxed0113;
+ const char16_t* expectedStrict0113;
+ const char16_t* expectedRelaxed1133;
+ const char16_t* expectedStrict1133;
+ } cases[] = {
+ { 0.9999, u"1", u"1", u"1.00", u"1.0" },
+ { 9.9999, u"10", u"10", u"10.0", u"10.0" },
+ { 99.999, u"100", u"100", u"100.0", u"100" },
+ { 999.99, u"1000", u"1000", u"1000.0", u"1000" },
+
+ { 0, u"0", u"0", u"0.00", u"0.0" },
+
+ { 9.876, u"9.88", u"9.9", u"9.88", u"9.9" },
+ { 9.001, u"9", u"9", u"9.00", u"9.0" },
+ };
+ for (const auto& cas : cases) {
+ auto precisionRelaxed0113 = Precision::minMaxFraction(0, 1)
+ .withSignificantDigits(1, 3, UNUM_ROUNDING_PRIORITY_RELAXED);
+ auto precisionStrict0113 = Precision::minMaxFraction(0, 1)
+ .withSignificantDigits(1, 3, UNUM_ROUNDING_PRIORITY_STRICT);
+ auto precisionRelaxed1133 = Precision::minMaxFraction(1, 1)
+ .withSignificantDigits(3, 3, UNUM_ROUNDING_PRIORITY_RELAXED);
+ auto precisionStrict1133 = Precision::minMaxFraction(1, 1)
+ .withSignificantDigits(3, 3, UNUM_ROUNDING_PRIORITY_STRICT);
+
+ auto messageBase = DoubleToUnicodeString(cas.input);
+
+ auto check = [&](
+ const char16_t* name,
+ const UnicodeString& expected,
+ const Precision& precision
+ ) {
+ assertEquals(
+ messageBase + name,
+ expected,
+ NumberFormatter::withLocale(Locale::getEnglish())
+ .precision(precision)
+ .grouping(UNUM_GROUPING_OFF)
+ .formatDouble(cas.input, status)
+ .toString(status)
+ );
+ };
+
+ check(u" Relaxed 0113", cas.expectedRelaxed0113, precisionRelaxed0113);
+ if (status.errIfFailureAndReset()) continue;
+
+ check(u" Strict 0113", cas.expectedStrict0113, precisionStrict0113);
+ if (status.errIfFailureAndReset()) continue;
+
+ check(u" Relaxed 1133", cas.expectedRelaxed1133, precisionRelaxed1133);
+ if (status.errIfFailureAndReset()) continue;
+
+ check(u" Strict 1133", cas.expectedStrict1133, precisionStrict1133);
+ if (status.errIfFailureAndReset()) continue;
+ }
+}
+
void NumberFormatterApiTest::grouping() {
assertFormatDescendingBig(
u"Western Grouping",
maxSignificantDigits >= minSignificantDigits &&
maxSignificantDigits <= RoundingUtils.MAX_INT_FRAC_SIG) {
return constructFractionSignificant(
- this, minSignificantDigits, maxSignificantDigits, priority);
+ this, minSignificantDigits, maxSignificantDigits, priority, false);
} else {
throw new IllegalArgumentException("Significant digits must be between 1 and "
+ RoundingUtils.MAX_INT_FRAC_SIG
public Precision withMinDigits(int minSignificantDigits) {
if (minSignificantDigits >= 1 && minSignificantDigits <= RoundingUtils.MAX_INT_FRAC_SIG) {
return constructFractionSignificant(
- this, 1, minSignificantDigits, NumberFormatter.RoundingPriority.RELAXED);
+ this, 1, minSignificantDigits, NumberFormatter.RoundingPriority.RELAXED, true);
} else {
throw new IllegalArgumentException("Significant digits must be between 1 and "
+ RoundingUtils.MAX_INT_FRAC_SIG
public Precision withMaxDigits(int maxSignificantDigits) {
if (maxSignificantDigits >= 1 && maxSignificantDigits <= RoundingUtils.MAX_INT_FRAC_SIG) {
return constructFractionSignificant(
- this, 1, maxSignificantDigits, NumberFormatter.RoundingPriority.STRICT);
+ this, 1, maxSignificantDigits, NumberFormatter.RoundingPriority.STRICT, true);
} else {
throw new IllegalArgumentException("Significant digits must be between 1 and "
+ RoundingUtils.MAX_INT_FRAC_SIG
// @, @@, @@@
maxSig = minSig;
}
- RoundingPriority priority;
+ FractionPrecision oldRounder = (FractionPrecision) macros.precision;
if (offset < segment.length()) {
+ RoundingPriority priority;
if (maxSig == -1) {
throw new SkeletonSyntaxException(
"Invalid digits option: Wildcard character not allowed with the priority annotation", segment);
throw new SkeletonSyntaxException(
"Invalid digits option for fraction rounder", segment);
}
+ macros.precision = oldRounder.withSignificantDigits(minSig, maxSig, priority);
} else if (maxSig == -1) {
// withMinDigits
- maxSig = minSig;
- minSig = 1;
- priority = RoundingPriority.RELAXED;
+ macros.precision = oldRounder.withMinDigits(minSig);
} else if (minSig == 1) {
// withMaxDigits
- priority = RoundingPriority.STRICT;
+ macros.precision = oldRounder.withMaxDigits(maxSig);
} else {
throw new SkeletonSyntaxException(
"Invalid digits option: Priority annotation required", segment);
}
- FractionPrecision oldRounder = (FractionPrecision) macros.precision;
- macros.precision = oldRounder.withSignificantDigits(minSig, maxSig, priority);
return true;
}
Precision.FracSigRounderImpl impl = (Precision.FracSigRounderImpl) macros.precision;
BlueprintHelpers.generateFractionStem(impl.minFrac, impl.maxFrac, sb);
sb.append('/');
- BlueprintHelpers.generateDigitsStem(impl.minSig, impl.maxSig, sb);
- if (impl.priority == RoundingPriority.RELAXED) {
- sb.append('r');
+ if (impl.retain) {
+ if (impl.priority == RoundingPriority.RELAXED) {
+ BlueprintHelpers.generateDigitsStem(impl.maxSig, -1, sb);
+ } else {
+ BlueprintHelpers.generateDigitsStem(1, impl.maxSig, sb);
+ }
} else {
- sb.append('s');
+ BlueprintHelpers.generateDigitsStem(impl.minSig, impl.maxSig, sb);
+ if (impl.priority == RoundingPriority.RELAXED) {
+ sb.append('r');
+ } else {
+ sb.append('s');
+ }
}
} else if (macros.precision instanceof Precision.IncrementRounderImpl) {
Precision.IncrementRounderImpl impl = (Precision.IncrementRounderImpl) macros.precision;
static final SignificantRounderImpl FIXED_SIG_3 = new SignificantRounderImpl(3, 3);
static final SignificantRounderImpl RANGE_SIG_2_3 = new SignificantRounderImpl(2, 3);
- static final FracSigRounderImpl COMPACT_STRATEGY = new FracSigRounderImpl(0, 0, 1, 2, RoundingPriority.RELAXED);
+ static final FracSigRounderImpl COMPACT_STRATEGY = new FracSigRounderImpl(0, 0, 1, 2, RoundingPriority.RELAXED,
+ false);
static final IncrementFiveRounderImpl NICKEL = new IncrementFiveRounderImpl(new BigDecimal("0.05"), 2, 2);
}
}
- static Precision constructFractionSignificant(
- FractionPrecision base_, int minSig, int maxSig, RoundingPriority priority) {
+ static Precision constructFractionSignificant(FractionPrecision base_, int minSig, int maxSig,
+ RoundingPriority priority, boolean retain) {
assert base_ instanceof FractionRounderImpl;
FractionRounderImpl base = (FractionRounderImpl) base_;
Precision returnValue;
- if (base.minFrac == 0 && base.maxFrac == 0 && minSig == 1 && maxSig == 2 &&
- priority == RoundingPriority.RELAXED) {
+ if (base.minFrac == 0 && base.maxFrac == 0 && minSig == 1 && maxSig == 2 && priority == RoundingPriority.RELAXED
+ && !retain) {
returnValue = COMPACT_STRATEGY;
} else {
- returnValue = new FracSigRounderImpl(base.minFrac, base.maxFrac, minSig, maxSig, priority);
+ returnValue = new FracSigRounderImpl(base.minFrac, base.maxFrac, minSig, maxSig, priority, retain);
}
return returnValue.withMode(base.mathContext);
}
final int minSig;
final int maxSig;
final RoundingPriority priority;
+ final boolean retain;
- public FracSigRounderImpl(int minFrac, int maxFrac, int minSig, int maxSig, RoundingPriority priority) {
+ public FracSigRounderImpl(int minFrac, int maxFrac, int minSig, int maxSig, RoundingPriority priority,
+ boolean retain) {
this.minFrac = minFrac;
this.maxFrac = maxFrac;
this.minSig = minSig;
this.maxSig = maxSig;
this.priority = priority;
+ this.retain = retain;
}
@Override
} else {
roundingMag = Math.max(roundingMag1, roundingMag2);
}
- value.roundToMagnitude(roundingMag, mathContext);
+ if (!value.isZeroish()) {
+ int upperMag = value.getMagnitude();
+ value.roundToMagnitude(roundingMag, mathContext);
+ if (!value.isZeroish() && value.getMagnitude() != upperMag && roundingMag1 == roundingMag2) {
+ // roundingMag2 needs to be the magnitude after rounding
+ roundingMag2 += 1;
+ }
+ }
int displayMag1 = getDisplayMagnitudeFraction(minFrac);
int displayMag2 = getDisplayMagnitudeSignificant(value, minSig);
- int displayMag = Math.min(displayMag1, displayMag2);
+ int displayMag;
+ if (retain) {
+ // withMinDigits + withMaxDigits
+ displayMag = Math.min(displayMag1, displayMag2);
+ } else if (priority == RoundingPriority.RELAXED) {
+ if (roundingMag2 <= roundingMag1) {
+ displayMag = displayMag2;
+ } else {
+ displayMag = displayMag1;
+ }
+ } else {
+ assert(priority == RoundingPriority.STRICT);
+ if (roundingMag2 <= roundingMag1) {
+ displayMag = displayMag1;
+ } else {
+ displayMag = displayMag2;
+ }
+ }
setResolvedMinFraction(value, Math.max(0, -displayMag));
}
@Override
FracSigRounderImpl createCopy() {
- FracSigRounderImpl copy = new FracSigRounderImpl(minFrac, maxFrac, minSig, maxSig, priority);
+ FracSigRounderImpl copy = new FracSigRounderImpl(minFrac, maxFrac, minSig, maxSig, priority, retain);
copy.mathContext = mathContext;
return copy;
}
ULocale.ENGLISH,
1.2,
"1.20");
-
+
assertFormatSingle(
"Hide If Whole B",
".00/w",
-98.7654321,
"-98.8");
+ assertFormatSingle(
+ "Fixed Significant at rounding boundary",
+ "@@@",
+ "@@@",
+ NumberFormatter.with().precision(Precision.fixedSignificantDigits(3)),
+ ULocale.ENGLISH,
+ 9.999,
+ "10.0");
+
assertFormatSingle(
"Fixed Significant Zero",
"@@@",
assertFormatDescending(
"FracSig withSignificantDigits STRICT",
"precision-integer/@#s",
- "./@#",
+ "./@#s",
NumberFormatter.with().precision(Precision.maxFraction(0)
.withSignificantDigits(1, 2, RoundingPriority.STRICT)),
ULocale.ENGLISH,
"0",
"0",
"0");
-
+
assertFormatSingle(
"FracSig withSignificantDigits Trailing Zeros RELAXED",
".0/@@@r",
ULocale.ENGLISH,
1,
"1.00");
-
- // Trailing zeros are always retained:
+
+ // Trailing zeros follow the strategy that was chosen:
assertFormatSingle(
"FracSig withSignificantDigits Trailing Zeros STRICT",
".0/@@@s",
.withSignificantDigits(3, 3, RoundingPriority.STRICT)),
ULocale.ENGLISH,
1,
- "1.00");
+ "1.0");
assertFormatSingle(
"FracSig withSignificantDigits at rounding boundary",
.withSignificantDigits(3, 3, RoundingPriority.STRICT)),
ULocale.ENGLISH,
9.99,
- "10.0");
+ "10");
assertFormatSingle(
"FracSig with Trailing Zero Display",
"50",
"50",
"0");
-
+
assertFormatDescending(
"Large nickel increment with rounding mode up (ICU-21668)",
"precision-increment/5000 rounding-mode-up",
"5,000",
"5,000",
"0");
-
+
assertFormatDescending(
"Large dime increment with rounding mode up (ICU-21668)",
"precision-increment/10000 rounding-mode-up",
"10,000",
"10,000",
"0");
-
+
assertFormatDescending(
"Large non-nickel increment with rounding mode up (ICU-21668)",
"precision-increment/15000 rounding-mode-up",
assertEquals("ICU-21668", "5,000", increment);
}
+ static interface RoundingPriorityCheckFn {
+ void check(String name, String expected, Precision precision);
+ }
+
+ @Test
+ public void roundingPriorityCoverageTest() {
+ String[][] cases = new String[][] {
+ // Input, relaxed 0113, strict 0113, relaxed 1133, strict 1133
+ { "0.9999", "1", "1", "1.00", "1.0" },
+ { "9.9999", "10", "10", "10.0", "10.0" },
+ { "99.999", "100", "100", "100.0", "100" },
+ { "999.99", "1000", "1000", "1000.0", "1000" },
+
+ { "0", "0", "0", "0.00", "0.0" },
+
+ { "9.876", "9.88", "9.9", "9.88", "9.9" },
+ { "9.001", "9", "9", "9.00", "9.0" },
+ };
+ for (String[] cas : cases) {
+ final double input = Double.parseDouble(cas[0]);
+ String expectedRelaxed0113 = cas[1];
+ String expectedStrict0113 = cas[2];
+ String expectedRelaxed1133 = cas[3];
+ String expectedStrict1133 = cas[4];
+
+ Precision precisionRelaxed0113 = Precision.minMaxFraction(0, 1)
+ .withSignificantDigits(1, 3, RoundingPriority.RELAXED);
+ Precision precisionStrict0113 = Precision.minMaxFraction(0, 1)
+ .withSignificantDigits(1, 3, RoundingPriority.STRICT);
+ Precision precisionRelaxed1133 = Precision.minMaxFraction(1, 1)
+ .withSignificantDigits(3, 3, RoundingPriority.RELAXED);
+ Precision precisionStrict1133 = Precision.minMaxFraction(1, 1)
+ .withSignificantDigits(3, 3, RoundingPriority.STRICT);
+
+ final String messageBase = cas[0];
+
+ RoundingPriorityCheckFn checker = new RoundingPriorityCheckFn() {
+ @Override
+ public void check(String name, String expected, Precision precision) {
+ assertEquals(
+ messageBase + name,
+ expected,
+ NumberFormatter.withLocale(ULocale.ENGLISH)
+ .precision(precision)
+ .grouping(GroupingStrategy.OFF)
+ .format(input)
+ .toString()
+ );
+ }
+ };
+
+ checker.check(" Relaxed 0113", expectedRelaxed0113, precisionRelaxed0113);
+
+ checker.check(" Strict 0113", expectedStrict0113, precisionStrict0113);
+
+ checker.check(" Relaxed 1133", expectedRelaxed1133, precisionRelaxed1133);
+
+ checker.check(" Strict 1133", expectedStrict1133, precisionStrict1133);
+ }
+ }
+
@Test
public void grouping() {
assertFormatDescendingBig(
ULocale.ENGLISH,
444444,
"444,444");
-
+
assertFormatSingle(
"Sign Negative Negative",
"sign-negative",
ULocale.ENGLISH,
-444444,
"-444,444");
-
+
assertFormatSingle(
"Sign Negative Negative Zero",
"sign-negative",
ULocale.ENGLISH,
-0.0000001,
"0");
-
+
assertFormatSingle(
"Sign Accounting-Negative Positive",
"currency/USD sign-accounting-negative",
ULocale.ENGLISH,
444444,
"$444,444.00");
-
+
assertFormatSingle(
"Sign Accounting-Negative Negative",
"currency/USD sign-accounting-negative",