return (flags & NEGATIVE_FLAG) != 0;
}
+int8_t DecimalQuantity::signum() const {
+ return isNegative() ? -1 : isZero() ? 0 : 1;
+}
+
bool DecimalQuantity::isInfinite() const {
return (flags & INFINITY_FLAG) != 0;
}
/** @return Whether the value represented by this {@link DecimalQuantity} is less than zero. */
bool isNegative() const;
+ /** @return -1 if the value is negative; 1 if positive; or 0 if zero. */
+ int8_t signum() const;
+
/** @return Whether the value represented by this {@link DecimalQuantity} is infinite. */
bool isInfinite() const U_OVERRIDE;
bool isPercent = isNoUnit && unitIsPercent(macros.unit);
bool isPermille = isNoUnit && unitIsPermille(macros.unit);
bool isCldrUnit = !isCurrency && !isNoUnit;
- bool isAccounting =
- macros.sign == UNUM_SIGN_ACCOUNTING || macros.sign == UNUM_SIGN_ACCOUNTING_ALWAYS;
+ bool isAccounting = macros.sign == UNUM_SIGN_ACCOUNTING
+ || macros.sign == UNUM_SIGN_ACCOUNTING_ALWAYS
+ || macros.sign == UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO;
CurrencyUnit currency(kDefaultCurrency, status);
if (isCurrency) {
currency = CurrencyUnit(macros.unit, status); // Restore CurrencyUnit from MeasureUnit
}
}
- void adoptPositiveNegativeModifiers(const Modifier *positive, const Modifier *negative) {
- mods[0] = positive;
- mods[1] = negative;
+ void adoptPositiveNegativeModifiers(
+ const Modifier *positive, const Modifier *zero, const Modifier *negative) {
+ mods[2] = positive;
+ mods[1] = zero;
+ mods[0] = negative;
}
/** The modifier is ADOPTED. */
- void adoptSignPluralModifier(bool isNegative, StandardPlural::Form plural, const Modifier *mod) {
- mods[getModIndex(isNegative, plural)] = mod;
+ void adoptSignPluralModifier(int8_t signum, StandardPlural::Form plural, const Modifier *mod) {
+ mods[getModIndex(signum, plural)] = mod;
}
/** Returns a reference to the modifier; no ownership change. */
- const Modifier *getModifier(bool isNegative) const {
- return mods[isNegative ? 1 : 0];
+ const Modifier *getModifier(int8_t signum) const {
+ return mods[signum + 1];
}
/** Returns a reference to the modifier; no ownership change. */
- const Modifier *getModifier(bool isNegative, StandardPlural::Form plural) const {
- return mods[getModIndex(isNegative, plural)];
+ const Modifier *getModifier(int8_t signum, StandardPlural::Form plural) const {
+ return mods[getModIndex(signum, plural)];
}
private:
- const Modifier *mods[2 * StandardPlural::COUNT];
+ const Modifier *mods[3 * StandardPlural::COUNT];
- inline static int32_t getModIndex(bool isNegative, StandardPlural::Form plural) {
- return static_cast<int32_t>(plural) * 2 + (isNegative ? 1 : 0);
+ inline static int32_t getModIndex(int8_t signum, StandardPlural::Form plural) {
+ return static_cast<int32_t>(plural) * 3 + (signum + 1);
}
};
this->rules = rules;
}
-void MutablePatternModifier::setNumberProperties(bool isNegative, StandardPlural::Form plural) {
- this->isNegative = isNegative;
+void MutablePatternModifier::setNumberProperties(int8_t signum, StandardPlural::Form plural) {
+ this->signum = signum;
this->plural = plural;
}
if (needsPlurals()) {
// Slower path when we require the plural keyword.
for (StandardPlural::Form plural : STANDARD_PLURAL_VALUES) {
- setNumberProperties(false, plural);
- pm->adoptSignPluralModifier(false, plural, createConstantModifier(status));
- setNumberProperties(true, plural);
- pm->adoptSignPluralModifier(true, plural, createConstantModifier(status));
+ setNumberProperties(1, plural);
+ pm->adoptSignPluralModifier(1, plural, createConstantModifier(status));
+ setNumberProperties(0, plural);
+ pm->adoptSignPluralModifier(0, plural, createConstantModifier(status));
+ setNumberProperties(-1, plural);
+ pm->adoptSignPluralModifier(-1, plural, createConstantModifier(status));
}
if (U_FAILURE(status)) {
delete pm;
return new ImmutablePatternModifier(pm, rules, parent); // adopts pm
} else {
// Faster path when plural keyword is not needed.
- setNumberProperties(false, StandardPlural::Form::COUNT);
+ setNumberProperties(1, StandardPlural::Form::COUNT);
Modifier *positive = createConstantModifier(status);
- setNumberProperties(true, StandardPlural::Form::COUNT);
+ setNumberProperties(0, StandardPlural::Form::COUNT);
+ Modifier *zero = createConstantModifier(status);
+ setNumberProperties(-1, StandardPlural::Form::COUNT);
Modifier *negative = createConstantModifier(status);
- pm->adoptPositiveNegativeModifiers(positive, negative);
+ pm->adoptPositiveNegativeModifiers(positive, zero, negative);
if (U_FAILURE(status)) {
delete pm;
return nullptr;
void ImmutablePatternModifier::applyToMicros(MicroProps µs, DecimalQuantity &quantity) const {
if (rules == nullptr) {
- micros.modMiddle = pm->getModifier(quantity.isNegative());
+ micros.modMiddle = pm->getModifier(quantity.signum());
} else {
// TODO: Fix this. Avoid the copy.
DecimalQuantity copy(quantity);
copy.roundToInfinity();
StandardPlural::Form plural = copy.getStandardPlural(rules);
- micros.modMiddle = pm->getModifier(quantity.isNegative(), plural);
+ micros.modMiddle = pm->getModifier(quantity.signum(), plural);
}
}
// TODO: Fix this. Avoid the copy.
DecimalQuantity copy(fq);
micros.rounding.apply(copy, status);
- nonConstThis->setNumberProperties(fq.isNegative(), copy.getStandardPlural(rules));
+ nonConstThis->setNumberProperties(fq.signum(), copy.getStandardPlural(rules));
} else {
- nonConstThis->setNumberProperties(fq.isNegative(), StandardPlural::Form::COUNT);
+ nonConstThis->setNumberProperties(fq.signum(), StandardPlural::Form::COUNT);
}
micros.modMiddle = this;
}
inCharSequenceMode = true;
// Should the output render '+' where '-' would normally appear in the pattern?
- plusReplacesMinusSign = !isNegative && (
- signDisplay == UNUM_SIGN_ALWAYS ||
- signDisplay == UNUM_SIGN_ACCOUNTING_ALWAYS) &&
- patternInfo->positiveHasPlusSign() == false;
+ plusReplacesMinusSign = signum != -1
+ && (signDisplay == UNUM_SIGN_ALWAYS
+ || signDisplay == UNUM_SIGN_ACCOUNTING_ALWAYS
+ || (signum == 1
+ && (signDisplay == UNUM_SIGN_EXCEPT_ZERO
+ || signDisplay == UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO)))
+ && patternInfo->positiveHasPlusSign() == false;
// Should we use the affix from the negative subpattern? (If not, we will use the positive subpattern.)
bool useNegativeAffixPattern = patternInfo->hasNegativeSubpattern() && (
- isNegative || (patternInfo->negativeHasMinusSign() && plusReplacesMinusSign));
+ signum == -1 || (patternInfo->negativeHasMinusSign() && plusReplacesMinusSign));
// Resolve the flags for the affix pattern.
fFlags = 0;
// Should we prepend a sign to the pattern?
if (!isPrefix || useNegativeAffixPattern) {
prependSign = false;
- } else if (isNegative) {
+ } else if (signum == -1) {
prependSign = signDisplay != UNUM_SIGN_NEVER;
} else {
prependSign = plusReplacesMinusSign;
/**
* Sets attributes of the current number being processed.
*
- * @param isNegative
- * Whether the number is negative.
+ * @param signum
+ * -1 if negative; +1 if positive; or 0 if zero.
* @param plural
- * The plural form of the number, required only if the pattern contains the triple currency sign, "¤¤¤"
- * (and as indicated by {@link #needsPlurals()}).
+ * The plural form of the number, required only if the pattern contains the triple
+ * currency sign, "¤¤¤" (and as indicated by {@link #needsPlurals()}).
*/
- void setNumberProperties(bool isNegative, StandardPlural::Form plural);
+ void setNumberProperties(int8_t signum, StandardPlural::Form plural);
/**
* Returns true if the pattern represented by this MurkyModifier requires a plural keyword in order to localize.
const PluralRules *rules;
// Number details (initialized in setNumberProperties)
- bool isNegative;
+ int8_t signum;
StandardPlural::Form plural;
// QuantityChain details (initialized in addToChain)
*
* @draft ICU 60
*/
- UNUM_SIGN_AUTO,
+ UNUM_SIGN_AUTO,
/**
- * Show the minus sign on negative numbers and the plus sign on positive numbers.
+ * Show the minus sign on negative numbers and the plus sign on positive numbers, including zero.
+ * To hide the sign on zero, see {@link UNUM_SIGN_EXCEPT_ZERO}.
*
* @draft ICU 60
*/
- UNUM_SIGN_ALWAYS,
+ UNUM_SIGN_ALWAYS,
/**
* Do not show the sign on positive or negative numbers.
*
* @draft ICU 60
*/
- UNUM_SIGN_NEVER,
+ UNUM_SIGN_NEVER,
/**
* Use the locale-dependent accounting format on negative numbers, and do not show the sign on positive numbers.
*
* @draft ICU 60
*/
- UNUM_SIGN_ACCOUNTING,
+ UNUM_SIGN_ACCOUNTING,
/**
- * Use the locale-dependent accounting format on negative numbers, and show the plus sign on positive numbers.
- * For more information on the accounting format, see the ACCOUNTING sign display strategy.
+ * Use the locale-dependent accounting format on negative numbers, and show the plus sign on
+ * positive numbers, including zero. For more information on the accounting format, see the
+ * ACCOUNTING sign display strategy. To hide the sign on zero, see
+ * {@link UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO}.
*
* @draft ICU 60
*/
- UNUM_SIGN_ACCOUNTING_ALWAYS,
+ UNUM_SIGN_ACCOUNTING_ALWAYS,
+
+ /**
+ * Show the minus sign on negative numbers and the plus sign on positive numbers. Do not show a
+ * sign on zero.
+ *
+ * @draft ICU 61
+ */
+ UNUM_SIGN_EXCEPT_ZERO,
+
+ /**
+ * Use the locale-dependent accounting format on negative numbers, and show the plus sign on
+ * positive numbers. Do not show a sign on zero. For more information on the accounting format,
+ * see the ACCOUNTING sign display strategy.
+ *
+ * @draft ICU 61
+ */
+ UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO,
/**
* One more than the highest UNumberSignDisplay value.
*
* @internal ICU 60: The numeric value may change over time; see ICU ticket #12420.
*/
- UNUM_SIGN_COUNT
+ UNUM_SIGN_COUNT
} UNumberSignDisplay;
/**
-444444,
u"-444,444");
+ assertFormatSingle(
+ u"Sign Auto Zero",
+ NumberFormatter::with().sign(UNumberSignDisplay::UNUM_SIGN_AUTO),
+ Locale::getEnglish(),
+ 0,
+ u"0");
+
assertFormatSingle(
u"Sign Always Positive",
NumberFormatter::with().sign(UNumberSignDisplay::UNUM_SIGN_ALWAYS),
-444444,
u"-444,444");
+ assertFormatSingle(
+ u"Sign Always Zero",
+ NumberFormatter::with().sign(UNumberSignDisplay::UNUM_SIGN_ALWAYS),
+ Locale::getEnglish(),
+ 0,
+ u"+0");
+
assertFormatSingle(
u"Sign Never Positive",
NumberFormatter::with().sign(UNumberSignDisplay::UNUM_SIGN_NEVER),
-444444,
u"444,444");
+ assertFormatSingle(
+ u"Sign Never Zero",
+ NumberFormatter::with().sign(UNumberSignDisplay::UNUM_SIGN_NEVER),
+ Locale::getEnglish(),
+ 0,
+ u"0");
+
assertFormatSingle(
u"Sign Accounting Positive",
NumberFormatter::with().sign(UNumberSignDisplay::UNUM_SIGN_ACCOUNTING).unit(USD),
-444444,
u"($444,444.00)");
+ assertFormatSingle(
+ u"Sign Accounting Zero",
+ NumberFormatter::with().sign(UNumberSignDisplay::UNUM_SIGN_ACCOUNTING).unit(USD),
+ Locale::getEnglish(),
+ 0,
+ u"$0.00");
+
assertFormatSingle(
u"Sign Accounting-Always Positive",
NumberFormatter::with().sign(UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_ALWAYS).unit(USD),
-444444,
u"($444,444.00)");
+ assertFormatSingle(
+ u"Sign Accounting-Always Zero",
+ NumberFormatter::with().sign(UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_ALWAYS).unit(USD),
+ Locale::getEnglish(),
+ 0,
+ u"+$0.00");
+
+ assertFormatSingle(
+ u"Sign Except-Zero Positive",
+ NumberFormatter::with().sign(UNumberSignDisplay::UNUM_SIGN_EXCEPT_ZERO),
+ Locale::getEnglish(),
+ 444444,
+ u"+444,444");
+
+ assertFormatSingle(
+ u"Sign Except-Zero Negative",
+ NumberFormatter::with().sign(UNumberSignDisplay::UNUM_SIGN_EXCEPT_ZERO),
+ Locale::getEnglish(),
+ -444444,
+ u"-444,444");
+
+ assertFormatSingle(
+ u"Sign Except-Zero Zero",
+ NumberFormatter::with().sign(UNumberSignDisplay::UNUM_SIGN_EXCEPT_ZERO),
+ Locale::getEnglish(),
+ 0,
+ u"0");
+
+ assertFormatSingle(
+ u"Sign Accounting-Except-Zero Positive",
+ NumberFormatter::with().sign(UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO).unit(USD),
+ Locale::getEnglish(),
+ 444444,
+ u"+$444,444.00");
+
+ assertFormatSingle(
+ u"Sign Accounting-Except-Zero Negative",
+ NumberFormatter::with().sign(UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO).unit(USD),
+ Locale::getEnglish(),
+ -444444,
+ u"($444,444.00)");
+
+ assertFormatSingle(
+ u"Sign Accounting-Except-Zero Zero",
+ NumberFormatter::with().sign(UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO).unit(USD),
+ Locale::getEnglish(),
+ 0,
+ u"$0.00");
+
assertFormatSingle(
u"Sign Accounting Negative Hidden",
NumberFormatter::with().sign(UNumberSignDisplay::UNUM_SIGN_ACCOUNTING)
assertSuccess("Spot 2", status);
mod.setSymbols(&symbols, currency, UNUM_UNIT_WIDTH_SHORT, nullptr);
- mod.setNumberProperties(false, StandardPlural::Form::COUNT);
+ mod.setNumberProperties(1, StandardPlural::Form::COUNT);
assertEquals("Pattern a0b", u"a", getPrefix(mod, status));
assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
mod.setPatternAttributes(UNUM_SIGN_ALWAYS, false);
assertEquals("Pattern a0b", u"+a", getPrefix(mod, status));
assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
- mod.setNumberProperties(true, StandardPlural::Form::COUNT);
+ mod.setNumberProperties(0, StandardPlural::Form::COUNT);
+ assertEquals("Pattern a0b", u"+a", getPrefix(mod, status));
+ assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
+ mod.setPatternAttributes(UNUM_SIGN_EXCEPT_ZERO, false);
+ assertEquals("Pattern a0b", u"a", getPrefix(mod, status));
+ assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
+ mod.setNumberProperties(-1, StandardPlural::Form::COUNT);
assertEquals("Pattern a0b", u"-a", getPrefix(mod, status));
assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
mod.setPatternAttributes(UNUM_SIGN_NEVER, false);
assertSuccess("Spot 4", status);
mod.setPatternInfo(&patternInfo2);
mod.setPatternAttributes(UNUM_SIGN_AUTO, false);
- mod.setNumberProperties(false, StandardPlural::Form::COUNT);
+ mod.setNumberProperties(1, StandardPlural::Form::COUNT);
assertEquals("Pattern a0b;c-0d", u"a", getPrefix(mod, status));
assertEquals("Pattern a0b;c-0d", u"b", getSuffix(mod, status));
mod.setPatternAttributes(UNUM_SIGN_ALWAYS, false);
assertEquals("Pattern a0b;c-0d", u"c+", getPrefix(mod, status));
assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
- mod.setNumberProperties(true, StandardPlural::Form::COUNT);
+ mod.setNumberProperties(0, StandardPlural::Form::COUNT);
+ assertEquals("Pattern a0b;c-0d", u"c+", getPrefix(mod, status));
+ assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
+ mod.setPatternAttributes(UNUM_SIGN_EXCEPT_ZERO, false);
+ assertEquals("Pattern a0b;c-0d", u"a", getPrefix(mod, status));
+ assertEquals("Pattern a0b;c-0d", u"b", getSuffix(mod, status));
+ mod.setNumberProperties(-1, StandardPlural::Form::COUNT);
assertEquals("Pattern a0b;c-0d", u"c-", getPrefix(mod, status));
assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
mod.setPatternAttributes(UNUM_SIGN_NEVER, false);
- assertEquals(
- "Pattern a0b;c-0d",
- u"c-",
- getPrefix(mod, status)); // TODO: What should this behavior be?
+ // TODO: What should this behavior be?
+ assertEquals("Pattern a0b;c-0d", u"c-", getPrefix(mod, status));
assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
assertSuccess("Spot 5", status);
}
/** @return Whether the value represented by this {@link DecimalQuantity} is less than zero. */
public boolean isNegative();
+ /** @return -1 if the value is negative; 1 if positive; or 0 if zero. */
+ public int signum();
+
/** @return Whether the value represented by this {@link DecimalQuantity} is infinite. */
@Override
public boolean isInfinite();
return (flags & NEGATIVE_FLAG) != 0;
}
+ @Override
+ public int signum() {
+ return isNegative() ? -1 : isZero() ? 0 : 1;
+ }
+
@Override
public boolean isInfinite() {
return (flags & INFINITY_FLAG) != 0;
PluralRules rules;
// Number details
- boolean isNegative;
+ int signum;
StandardPlural plural;
// QuantityChain details
/**
* Sets attributes of the current number being processed.
*
- * @param isNegative
- * Whether the number is negative.
+ * @param signum
+ * -1 if negative; +1 if positive; or 0 if zero.
* @param plural
* The plural form of the number, required only if the pattern contains the triple
* currency sign, "¤¤¤" (and as indicated by {@link #needsPlurals()}).
*/
- public void setNumberProperties(boolean isNegative, StandardPlural plural) {
+ public void setNumberProperties(int signum, StandardPlural plural) {
assert (plural != null) == needsPlurals();
- this.isNegative = isNegative;
+ this.signum = signum;
this.plural = plural;
}
// Slower path when we require the plural keyword.
ParameterizedModifier pm = new ParameterizedModifier();
for (StandardPlural plural : StandardPlural.VALUES) {
- setNumberProperties(false, plural);
- pm.setModifier(false, plural, createConstantModifier(a, b));
- setNumberProperties(true, plural);
- pm.setModifier(true, plural, createConstantModifier(a, b));
+ setNumberProperties(1, plural);
+ pm.setModifier(1, plural, createConstantModifier(a, b));
+ setNumberProperties(0, plural);
+ pm.setModifier(0, plural, createConstantModifier(a, b));
+ setNumberProperties(-1, plural);
+ pm.setModifier(-1, plural, createConstantModifier(a, b));
}
pm.freeze();
return new ImmutablePatternModifier(pm, rules, parent);
} else {
// Faster path when plural keyword is not needed.
- setNumberProperties(false, null);
+ setNumberProperties(1, null);
Modifier positive = createConstantModifier(a, b);
- setNumberProperties(true, null);
+ setNumberProperties(0, null);
+ Modifier zero = createConstantModifier(a, b);
+ setNumberProperties(-1, null);
Modifier negative = createConstantModifier(a, b);
- ParameterizedModifier pm = new ParameterizedModifier(positive, negative);
+ ParameterizedModifier pm = new ParameterizedModifier(positive, zero, negative);
return new ImmutablePatternModifier(pm, null, parent);
}
}
public void applyToMicros(MicroProps micros, DecimalQuantity quantity) {
if (rules == null) {
- micros.modMiddle = pm.getModifier(quantity.isNegative());
+ micros.modMiddle = pm.getModifier(quantity.signum());
} else {
// TODO: Fix this. Avoid the copy.
DecimalQuantity copy = quantity.createCopy();
copy.roundToInfinity();
StandardPlural plural = copy.getStandardPlural(rules);
- micros.modMiddle = pm.getModifier(quantity.isNegative(), plural);
+ micros.modMiddle = pm.getModifier(quantity.signum(), plural);
}
}
}
// TODO: Fix this. Avoid the copy.
DecimalQuantity copy = fq.createCopy();
micros.rounding.apply(copy);
- setNumberProperties(fq.isNegative(), copy.getStandardPlural(rules));
+ setNumberProperties(fq.signum(), copy.getStandardPlural(rules));
} else {
- setNumberProperties(fq.isNegative(), null);
+ setNumberProperties(fq.signum(), null);
}
micros.modMiddle = this;
return micros;
inCharSequenceMode = true;
// Should the output render '+' where '-' would normally appear in the pattern?
- plusReplacesMinusSign = !isNegative
- && (signDisplay == SignDisplay.ALWAYS || signDisplay == SignDisplay.ACCOUNTING_ALWAYS)
+ plusReplacesMinusSign = signum != -1
+ && (signDisplay == SignDisplay.ALWAYS
+ || signDisplay == SignDisplay.ACCOUNTING_ALWAYS
+ || (signum == 1
+ && (signDisplay == SignDisplay.EXCEPT_ZERO
+ || signDisplay == SignDisplay.ACCOUNTING_EXCEPT_ZERO)))
&& patternInfo.positiveHasPlusSign() == false;
// Should we use the affix from the negative subpattern? (If not, we will use the positive
// subpattern.)
boolean useNegativeAffixPattern = patternInfo.hasNegativeSubpattern()
- && (isNegative || (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign));
+ && (signum == -1 || (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign));
// Resolve the flags for the affix pattern.
flags = 0;
// Should we prepend a sign to the pattern?
if (!isPrefix || useNegativeAffixPattern) {
prependSign = false;
- } else if (isNegative) {
+ } else if (signum == -1) {
prependSign = signDisplay != SignDisplay.NEVER;
} else {
prependSign = plusReplacesMinusSign;
*/
public class ParameterizedModifier {
private final Modifier positive;
+ private final Modifier zero;
private final Modifier negative;
final Modifier[] mods;
boolean frozen;
* <p>
* If this constructor is used, a plural form CANNOT be passed to {@link #getModifier}.
*/
- public ParameterizedModifier(Modifier positive, Modifier negative) {
+ public ParameterizedModifier(Modifier positive, Modifier zero, Modifier negative) {
this.positive = positive;
+ this.zero = zero;
this.negative = negative;
this.mods = null;
this.frozen = true;
*/
public ParameterizedModifier() {
this.positive = null;
+ this.zero = null;
this.negative = null;
- this.mods = new Modifier[2 * StandardPlural.COUNT];
+ this.mods = new Modifier[3 * StandardPlural.COUNT];
this.frozen = false;
}
- public void setModifier(boolean isNegative, StandardPlural plural, Modifier mod) {
+ public void setModifier(int signum, StandardPlural plural, Modifier mod) {
assert !frozen;
- mods[getModIndex(isNegative, plural)] = mod;
+ mods[getModIndex(signum, plural)] = mod;
}
public void freeze() {
frozen = true;
}
- public Modifier getModifier(boolean isNegative) {
+ public Modifier getModifier(int signum) {
assert frozen;
assert mods == null;
- return isNegative ? negative : positive;
+ return signum == 0 ? zero : signum < 0 ? negative : positive;
}
- public Modifier getModifier(boolean isNegative, StandardPlural plural) {
+ public Modifier getModifier(int signum, StandardPlural plural) {
assert frozen;
assert positive == null;
- return mods[getModIndex(isNegative, plural)];
+ return mods[getModIndex(signum, plural)];
}
- private static int getModIndex(boolean isNegative, StandardPlural plural) {
- return plural.ordinal() * 2 + (isNegative ? 1 : 0);
+ private static int getModIndex(int signum, StandardPlural plural) {
+ return plural.ordinal() * 3 + (signum + 1);
}
}
AUTO,
/**
- * Show the minus sign on negative numbers and the plus sign on positive numbers.
+ * Show the minus sign on negative numbers and the plus sign on positive numbers, including zero.
+ * To hide the sign on zero, see {@link #EXCEPT_ZERO}.
*
* @draft ICU 60
* @provisional This API might change or be removed in a future release.
/**
* Use the locale-dependent accounting format on negative numbers, and show the plus sign on
- * positive numbers. For more information on the accounting format, see the ACCOUNTING sign
- * display strategy.
+ * positive numbers, including zero. For more information on the accounting format, see the
+ * ACCOUNTING sign display strategy. To hide the sign on zero, see
+ * {@link #ACCOUNTING_EXCEPT_ZERO}.
*
* @draft ICU 60
* @provisional This API might change or be removed in a future release.
* @see NumberFormatter
*/
ACCOUNTING_ALWAYS,
+
+ /**
+ * Show the minus sign on negative numbers and the plus sign on positive numbers. Do not show a
+ * sign on zero.
+ *
+ * @draft ICU 61
+ * @provisional This API might change or be removed in a future release.
+ * @see NumberFormatter
+ */
+ EXCEPT_ZERO,
+
+ /**
+ * Use the locale-dependent accounting format on negative numbers, and show the plus sign on
+ * positive numbers. Do not show a sign on zero. For more information on the accounting format,
+ * see the ACCOUNTING sign display strategy.
+ *
+ * @draft ICU 61
+ * @provisional This API might change or be removed in a future release.
+ * @see NumberFormatter
+ */
+ ACCOUNTING_EXCEPT_ZERO,
}
/**
boolean isPermille = isNoUnit && unitIsPermille(macros.unit);
boolean isCldrUnit = !isCurrency && !isNoUnit;
boolean isAccounting = macros.sign == SignDisplay.ACCOUNTING
- || macros.sign == SignDisplay.ACCOUNTING_ALWAYS;
+ || macros.sign == SignDisplay.ACCOUNTING_ALWAYS
+ || macros.sign == SignDisplay.ACCOUNTING_EXCEPT_ZERO;
Currency currency = isCurrency ? (Currency) macros.unit : DEFAULT_CURRENCY;
UnitWidth unitWidth = UnitWidth.SHORT;
if (macros.unitWidth != null) {
return (flags & NEGATIVE_FLAG) != 0;
}
+ @Override
+ public int signum() {
+ return isNegative() ? -1 : isZero() ? 0 : 1;
+ }
+
private void setNegative(boolean isNegative) {
flags = (flags & (~NEGATIVE_FLAG)) | (isNegative ? NEGATIVE_FLAG : 0);
}
UnitWidth.SHORT,
null);
- mod.setNumberProperties(false, null);
+ mod.setNumberProperties(1, null);
assertEquals("a", getPrefix(mod));
assertEquals("b", getSuffix(mod));
mod.setPatternAttributes(SignDisplay.ALWAYS, false);
assertEquals("+a", getPrefix(mod));
assertEquals("b", getSuffix(mod));
- mod.setNumberProperties(true, null);
+ mod.setNumberProperties(0, null);
+ assertEquals("+a", getPrefix(mod));
+ assertEquals("b", getSuffix(mod));
+ mod.setPatternAttributes(SignDisplay.EXCEPT_ZERO, false);
+ assertEquals("a", getPrefix(mod));
+ assertEquals("b", getSuffix(mod));
+ mod.setNumberProperties(-1, null);
assertEquals("-a", getPrefix(mod));
assertEquals("b", getSuffix(mod));
mod.setPatternAttributes(SignDisplay.NEVER, false);
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b;c-0d"));
mod.setPatternAttributes(SignDisplay.AUTO, false);
- mod.setNumberProperties(false, null);
+ mod.setNumberProperties(1, null);
assertEquals("a", getPrefix(mod));
assertEquals("b", getSuffix(mod));
mod.setPatternAttributes(SignDisplay.ALWAYS, false);
assertEquals("c+", getPrefix(mod));
assertEquals("d", getSuffix(mod));
- mod.setNumberProperties(true, null);
+ mod.setNumberProperties(0, null);
+ assertEquals("c+", getPrefix(mod));
+ assertEquals("d", getSuffix(mod));
+ mod.setPatternAttributes(SignDisplay.EXCEPT_ZERO, false);
+ assertEquals("a", getPrefix(mod));
+ assertEquals("b", getSuffix(mod));
+ mod.setNumberProperties(-1, null);
assertEquals("c-", getPrefix(mod));
assertEquals("d", getSuffix(mod));
mod.setPatternAttributes(SignDisplay.NEVER, false);
-444444,
"-444,444");
+ assertFormatSingle(
+ "Sign Auto Zero",
+ "",
+ NumberFormatter.with().sign(SignDisplay.AUTO),
+ ULocale.ENGLISH,
+ 0,
+ "0");
+
assertFormatSingle(
"Sign Always Positive",
"sign=ALWAYS",
-444444,
"-444,444");
+ assertFormatSingle(
+ "Sign Always Zero",
+ "",
+ NumberFormatter.with().sign(SignDisplay.ALWAYS),
+ ULocale.ENGLISH,
+ 0,
+ "+0");
+
assertFormatSingle(
"Sign Never Positive",
"sign=NEVER",
-444444,
"444,444");
+ assertFormatSingle(
+ "Sign Never Zero",
+ "",
+ NumberFormatter.with().sign(SignDisplay.NEVER),
+ ULocale.ENGLISH,
+ 0,
+ "0");
+
assertFormatSingle(
"Sign Accounting Positive",
"$USD sign=ACCOUNTING",
-444444,
"($444,444.00)");
+ assertFormatSingle(
+ "Sign Accounting Zero",
+ "",
+ NumberFormatter.with().sign(SignDisplay.ACCOUNTING).unit(USD),
+ ULocale.ENGLISH,
+ 0,
+ "$0.00");
+
assertFormatSingle(
"Sign Accounting-Always Positive",
"$USD sign=ACCOUNTING_ALWAYS",
-444444,
"($444,444.00)");
+ assertFormatSingle(
+ "Sign Accounting-Always Zero",
+ "",
+ NumberFormatter.with().sign(SignDisplay.ACCOUNTING_ALWAYS).unit(USD),
+ ULocale.ENGLISH,
+ 0,
+ "+$0.00");
+
+ assertFormatSingle(
+ "Sign Except-Zero Positive",
+ "",
+ NumberFormatter.with().sign(SignDisplay.EXCEPT_ZERO),
+ ULocale.ENGLISH,
+ 444444,
+ "+444,444");
+
+ assertFormatSingle(
+ "Sign Always Negative",
+ "",
+ NumberFormatter.with().sign(SignDisplay.EXCEPT_ZERO),
+ ULocale.ENGLISH,
+ -444444,
+ "-444,444");
+
+ assertFormatSingle(
+ "Sign Except-Zero Zero",
+ "",
+ NumberFormatter.with().sign(SignDisplay.EXCEPT_ZERO),
+ ULocale.ENGLISH,
+ 0,
+ "0");
+
+ assertFormatSingle(
+ "Sign Accounting-Except-Zero Positive",
+ "$USD sign=ACCOUNTING_ALWAYS",
+ NumberFormatter.with().sign(SignDisplay.ACCOUNTING_EXCEPT_ZERO).unit(USD),
+ ULocale.ENGLISH,
+ 444444,
+ "+$444,444.00");
+
+ assertFormatSingle(
+ "Sign Accounting-Except-Zero Negative",
+ "$USD sign=ACCOUNTING_ALWAYS",
+ NumberFormatter.with().sign(SignDisplay.ACCOUNTING_EXCEPT_ZERO).unit(USD),
+ ULocale.ENGLISH,
+ -444444,
+ "($444,444.00)");
+
+ assertFormatSingle(
+ "Sign Accounting-Except-Zero Zero",
+ "",
+ NumberFormatter.with().sign(SignDisplay.ACCOUNTING_EXCEPT_ZERO).unit(USD),
+ ULocale.ENGLISH,
+ 0,
+ "$0.00");
+
assertFormatSingle(
"Sign Accounting Negative Hidden",
"$USD unit-width=HIDDEN sign=ACCOUNTING",