DecimalFormatpublic class DecimalFormat extends NumberFormat DecimalFormat is a concrete subclass of
NumberFormat that formats decimal numbers. It has a variety of
features designed to make it possible to parse and format numbers in any
locale, including support for Western, Arabic, and Indic digits. It also
supports different kinds of numbers, including integers (123), fixed-point
numbers (123.4), scientific notation (1.23E4), percentages (12%), and
currency amounts ($123). All of these can be localized.
To obtain a NumberFormat for a specific locale, including the
default locale, call one of NumberFormat 's factory methods, such
as getInstance() . In general, do not call the
DecimalFormat constructors directly, since the
NumberFormat factory methods may return subclasses other than
DecimalFormat . If you need to customize the format object, do
something like this:
NumberFormat f = NumberFormat.getInstance(loc);
if (f instanceof DecimalFormat) {
((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
}
A DecimalFormat comprises a pattern and a set of
symbols. The pattern may be set directly using
applyPattern() , or indirectly using the API methods. The
symbols are stored in a DecimalFormatSymbols object. When using
the NumberFormat factory methods, the pattern and symbols are
read from localized ResourceBundle s.
Patterns
DecimalFormat patterns have the following syntax:
Pattern:
PositivePattern
PositivePattern ; NegativePattern
PositivePattern:
Prefixopt Number Suffixopt
NegativePattern:
Prefixopt Number Suffixopt
Prefix:
any Unicode characters except \uFFFE, \uFFFF, and special characters
Suffix:
any Unicode characters except \uFFFE, \uFFFF, and special characters
Number:
Integer Exponentopt
Integer . Fraction Exponentopt
Integer:
MinimumInteger
#
# Integer
# , Integer
MinimumInteger:
0
0 MinimumInteger
0 , MinimumInteger
Fraction:
MinimumFractionopt OptionalFractionopt
MinimumFraction:
0 MinimumFractionopt
OptionalFraction:
# OptionalFractionopt
Exponent:
E MinimumExponent
MinimumExponent:
0 MinimumExponentopt
A DecimalFormat pattern contains a positive and negative
subpattern, for example, "#,##0.00;(#,##0.00)" . Each
subpattern has a prefix, numeric part, and suffix. The negative subpattern
is optional; if absent, then the positive subpattern prefixed with the
localized minus sign ('-' in most locales) is used as the
negative subpattern. That is, "0.00" alone is equivalent to
"0.00;-0.00" . If there is an explicit negative subpattern, it
serves only to specify the negative prefix and suffix; the number of digits,
minimal digits, and other characteristics are all the same as the positive
pattern. That means that "#,##0.0#;(#)" produces precisely
the same behavior as "#,##0.0#;(#,##0.0#)" .
The prefixes, suffixes, and various symbols used for infinity, digits,
thousands separators, decimal separators, etc. may be set to arbitrary
values, and they will appear properly during formatting. However, care must
be taken that the symbols and strings do not conflict, or parsing will be
unreliable. For example, either the positive and negative prefixes or the
suffixes must be distinct for DecimalFormat.parse() to be able
to distinguish positive from negative values. (If they are identical, then
DecimalFormat will behave as if no negative subpattern was
specified.) Another example is that the decimal separator and thousands
separator should be distinct characters, or parsing will be impossible.
The grouping separator is commonly used for thousands, but in some
countries it separates ten-thousands. The grouping size is a constant number
of digits between the grouping characters, such as 3 for 100,000,000 or 4 for
1,0000,0000. If you supply a pattern with multiple grouping characters, the
interval between the last one and the end of the integer is the one that is
used. So "#,##,###,####" == "######,####" ==
"##,####,####" .
Special Pattern Characters
Many characters in a pattern are taken literally; they are matched during
parsing and output unchanged during formatting. Special characters, on the
other hand, stand for other characters, strings, or classes of characters.
They must be quoted, unless noted otherwise, if they are to appear in the
prefix or suffix as literals.
The characters listed here are used in non-localized patterns. Localized
patterns use the corresponding characters taken from this formatter's
DecimalFormatSymbols object instead, and these characters lose
their special status. Two exceptions are the currency sign and quote, which
are not localized.
Symbol
| Location
| Localized?
| Meaning
|
0
| Number
| Yes
| Digit
|
#
| Number
| Yes
| Digit, zero shows as absent
|
.
| Number
| Yes
| Decimal separator or monetary decimal separator
|
-
| Number
| Yes
| Minus sign
|
,
| Number
| Yes
| Grouping separator
|
E
| Number
| Yes
| Separates mantissa and exponent in scientific notation.
Need not be quoted in prefix or suffix.
|
;
| Subpattern boundary
| Yes
| Separates positive and negative subpatterns
|
%
| Prefix or suffix
| Yes
| Multiply by 100 and show as percentage
|
\u2030
| Prefix or suffix
| Yes
| Multiply by 1000 and show as per mille value
|
¤ (\u00A4 )
| Prefix or suffix
| No
| Currency sign, replaced by currency symbol. If
doubled, replaced by international currency symbol.
If present in a pattern, the monetary decimal separator
is used instead of the decimal separator.
|
'
| Prefix or suffix
| No
| Used to quote special characters in a prefix or suffix,
for example, "'#'#" formats 123 to
"#123" . To create a single quote
itself, use two in a row: "# o''clock" .
|
Scientific Notation
Numbers in scientific notation are expressed as the product of a mantissa
and a power of ten, for example, 1234 can be expressed as 1.234 x 10^3. The
mantissa is often in the range 1.0 <= x < 10.0, but it need not be.
DecimalFormat can be instructed to format and parse scientific
notation only via a pattern; there is currently no factory method
that creates a scientific notation format. In a pattern, the exponent
character immediately followed by one or more digit characters indicates
scientific notation. Example: "0.###E0" formats the number
1234 as "1.234E3" .
- The number of digit characters after the exponent character gives the
minimum exponent digit count. There is no maximum. Negative exponents are
formatted using the localized minus sign, not the prefix and suffix
from the pattern. This allows patterns such as
"0.###E0 m/s" .
- The minimum and maximum number of integer digits are interpreted
together:
- If the maximum number of integer digits is greater than their minimum number
and greater than 1, it forces the exponent to be a multiple of the maximum
number of integer digits, and the minimum number of integer digits to be
interpreted as 1. The most common use of this is to generate
engineering notation, in which the exponent is a multiple of three,
e.g.,
"##0.#####E0" . Using this pattern, the number 12345
formats to "12.345E3" , and 123456 formats to
"123.456E3" .
- Otherwise, the minimum number of integer digits is achieved by adjusting the
exponent. Example: 0.00123 formatted with
"00.###E0" yields
"12.3E-4" .
- The number of significant digits in the mantissa is the sum of the
minimum integer and maximum fraction digits, and is
unaffected by the maximum integer digits. For example, 12345 formatted with
"##0.##E0" is "12.3E3" . To show all digits, set
the significant digits count to zero. The number of significant digits
does not affect parsing.
- Exponential patterns may not contain grouping separators.
Rounding
DecimalFormat provides rounding modes defined in
{@link java.math.RoundingMode} for formatting. By default, it uses
{@link java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}.
Digits
For formatting, DecimalFormat uses the ten consecutive
characters starting with the localized zero digit defined in the
DecimalFormatSymbols object as digits. For parsing, these
digits as well as all Unicode decimal digits, as defined by
{@link Character#digit Character.digit}, are recognized.
Special Values
NaN is formatted as a string, which typically has a single character
\uFFFD . This string is determined by the
DecimalFormatSymbols object. This is the only value for which
the prefixes and suffixes are not used.
Infinity is formatted as a string, which typically has a single character
\u221E , with the positive or negative prefixes and suffixes
applied. The infinity string is determined by the
DecimalFormatSymbols object.
Negative zero ("-0" ) parses to
BigDecimal(0) if isParseBigDecimal() is
true,
Long(0) if isParseBigDecimal() is false
and isParseIntegerOnly() is true,
Double(-0.0) if both isParseBigDecimal()
and isParseIntegerOnly() are false.
Decimal formats are generally not synchronized.
It is recommended to create separate format instances for each thread.
If multiple threads access a format concurrently, it must be synchronized
externally.
Example
// Print out a number using the localized number, integer, currency,
// and percent format for each locale
Locale[] locales = NumberFormat.getAvailableLocales();
double myNumber = -1234.56;
NumberFormat form;
for (int j=0; j<4; ++j) {
System.out.println("FORMAT");
for (int i = 0; i < locales.length; ++i) {
if (locales[i].getCountry().length() == 0) {
continue; // Skip language-only locales
}
System.out.print(locales[i].getDisplayName());
switch (j) {
case 0:
form = NumberFormat.getInstance(locales[i]); break;
case 1:
form = NumberFormat.getIntegerInstance(locales[i]); break;
case 2:
form = NumberFormat.getCurrencyInstance(locales[i]); break;
default:
form = NumberFormat.getPercentInstance(locales[i]); break;
}
if (form instanceof DecimalFormat) {
System.out.print(": " + ((DecimalFormat) form).toPattern());
}
System.out.print(" -> " + form.format(myNumber));
try {
System.out.println(" -> " + form.parse(form.format(myNumber)));
} catch (ParseException e) {}
}
}
|
Fields Summary |
---|
private transient BigInteger | bigIntegerMultiplier | private transient BigDecimal | bigDecimalMultiplier | private static final int | STATUS_INFINITE | private static final int | STATUS_POSITIVE | private static final int | STATUS_LENGTH | private transient DigitList | digitList | private String | positivePrefixThe symbol used as a prefix when formatting positive numbers, e.g. "+". | private String | positiveSuffixThe symbol used as a suffix when formatting positive numbers.
This is often an empty string. | private String | negativePrefixThe symbol used as a prefix when formatting negative numbers, e.g. "-". | private String | negativeSuffixThe symbol used as a suffix when formatting negative numbers.
This is often an empty string. | private String | posPrefixPatternThe prefix pattern for non-negative numbers. This variable corresponds
to positivePrefix .
This pattern is expanded by the method expandAffix() to
positivePrefix to update the latter to reflect changes in
symbols . If this variable is null then
positivePrefix is taken as a literal value that does not
change when symbols changes. This variable is always
null for DecimalFormat objects older than
stream version 2 restored from stream. | private String | posSuffixPatternThe suffix pattern for non-negative numbers. This variable corresponds
to positiveSuffix . This variable is analogous to
posPrefixPattern ; see that variable for further
documentation. | private String | negPrefixPatternThe prefix pattern for negative numbers. This variable corresponds
to negativePrefix . This variable is analogous to
posPrefixPattern ; see that variable for further
documentation. | private String | negSuffixPatternThe suffix pattern for negative numbers. This variable corresponds
to negativeSuffix . This variable is analogous to
posPrefixPattern ; see that variable for further
documentation. | private int | multiplierThe multiplier for use in percent, per mille, etc. | private byte | groupingSizeThe number of digits between grouping separators in the integer
portion of a number. Must be greater than 0 if
NumberFormat.groupingUsed is true. | private boolean | decimalSeparatorAlwaysShownIf true, forces the decimal separator to always appear in a formatted
number, even if the fractional part of the number is zero. | private boolean | parseBigDecimalIf true, parse returns BigDecimal wherever possible. | private transient boolean | isCurrencyFormatTrue if this object represents a currency format. This determines
whether the monetary decimal separator is used instead of the normal one. | private DecimalFormatSymbols | symbolsThe DecimalFormatSymbols object used by this format.
It contains the symbols used to format numbers, e.g. the grouping separator,
decimal separator, and so on. | private boolean | useExponentialNotationTrue to force the use of exponential (i.e. scientific) notation when formatting
numbers. | private transient FieldPosition[] | positivePrefixFieldPositionsFieldPositions describing the positive prefix String. This is
lazily created. Use getPositivePrefixFieldPositions
when needed. | private transient FieldPosition[] | positiveSuffixFieldPositionsFieldPositions describing the positive suffix String. This is
lazily created. Use getPositiveSuffixFieldPositions
when needed. | private transient FieldPosition[] | negativePrefixFieldPositionsFieldPositions describing the negative prefix String. This is
lazily created. Use getNegativePrefixFieldPositions
when needed. | private transient FieldPosition[] | negativeSuffixFieldPositionsFieldPositions describing the negative suffix String. This is
lazily created. Use getNegativeSuffixFieldPositions
when needed. | private byte | minExponentDigitsThe minimum number of digits used to display the exponent when a number is
formatted in exponential notation. This field is ignored if
useExponentialNotation is not true. | private int | maximumIntegerDigitsThe maximum number of digits allowed in the integer portion of a
BigInteger or BigDecimal number.
maximumIntegerDigits must be greater than or equal to
minimumIntegerDigits . | private int | minimumIntegerDigitsThe minimum number of digits allowed in the integer portion of a
BigInteger or BigDecimal number.
minimumIntegerDigits must be less than or equal to
maximumIntegerDigits . | private int | maximumFractionDigitsThe maximum number of digits allowed in the fractional portion of a
BigInteger or BigDecimal number.
maximumFractionDigits must be greater than or equal to
minimumFractionDigits . | private int | minimumFractionDigitsThe minimum number of digits allowed in the fractional portion of a
BigInteger or BigDecimal number.
minimumFractionDigits must be less than or equal to
maximumFractionDigits . | private RoundingMode | roundingModeThe {@link java.math.RoundingMode} used in this DecimalFormat. | static final int | currentSerialVersion | private int | serialVersionOnStreamThe internal serial version which says which version was written.
Possible values are:
- 0 (default): versions before the Java 2 platform v1.2
- 1: version for 1.2, which includes the two new fields
useExponentialNotation and
minExponentDigits .
- 2: version for 1.3 and later, which adds four new fields:
posPrefixPattern , posSuffixPattern ,
negPrefixPattern , and negSuffixPattern .
- 3: version for 1.5 and later, which adds five new fields:
maximumIntegerDigits ,
minimumIntegerDigits ,
maximumFractionDigits ,
minimumFractionDigits , and
parseBigDecimal .
- 4: version for 1.6 and later, which adds one new field:
roundingMode .
| private static final char | PATTERN_ZERO_DIGIT | private static final char | PATTERN_GROUPING_SEPARATOR | private static final char | PATTERN_DECIMAL_SEPARATOR | private static final char | PATTERN_PER_MILLE | private static final char | PATTERN_PERCENT | private static final char | PATTERN_DIGIT | private static final char | PATTERN_SEPARATOR | private static final String | PATTERN_EXPONENT | private static final char | PATTERN_MINUS | private static final char | CURRENCY_SIGNThe CURRENCY_SIGN is the standard Unicode symbol for currency. It
is used in patterns and substituted with either the currency symbol,
or if it is doubled, with the international currency symbol. If the
CURRENCY_SIGN is seen in a pattern, then the decimal separator is
replaced with the monetary decimal separator.
The CURRENCY_SIGN is not localized. | private static final char | QUOTE | private static FieldPosition[] | EmptyFieldPositionArray | static final int | DOUBLE_INTEGER_DIGITS | static final int | DOUBLE_FRACTION_DIGITS | static final int | MAXIMUM_INTEGER_DIGITS | static final int | MAXIMUM_FRACTION_DIGITS | static final long | serialVersionUID | private static Hashtable | cachedLocaleDataCache to hold the NumberPattern of a Locale. |
Constructors Summary |
---|
public DecimalFormat()Creates a DecimalFormat using the default pattern and symbols
for the default locale. This is a convenient way to obtain a
DecimalFormat when internationalization is not the main concern.
To obtain standard formats for a given locale, use the factory methods
on NumberFormat such as getNumberInstance. These factories will
return the most appropriate sub-class of NumberFormat for a given
locale.
Locale def = Locale.getDefault();
// try to get the pattern from the cache
String pattern = (String) cachedLocaleData.get(def);
if (pattern == null) { /* cache miss */
// Get the pattern for the default locale.
ResourceBundle rb = LocaleData.getNumberFormatData(def);
String[] all = rb.getStringArray("NumberPatterns");
pattern = all[0];
/* update cache */
cachedLocaleData.put(def, pattern);
}
// Always applyPattern after the symbols are set
this.symbols = new DecimalFormatSymbols(def);
applyPattern(pattern, false);
| public DecimalFormat(String pattern)Creates a DecimalFormat using the given pattern and the symbols
for the default locale. This is a convenient way to obtain a
DecimalFormat when internationalization is not the main concern.
To obtain standard formats for a given locale, use the factory methods
on NumberFormat such as getNumberInstance. These factories will
return the most appropriate sub-class of NumberFormat for a given
locale.
// Always applyPattern after the symbols are set
this.symbols = new DecimalFormatSymbols(Locale.getDefault());
applyPattern(pattern, false);
| public DecimalFormat(String pattern, DecimalFormatSymbols symbols)Creates a DecimalFormat using the given pattern and symbols.
Use this constructor when you need to completely customize the
behavior of the format.
To obtain standard formats for a given
locale, use the factory methods on NumberFormat such as
getInstance or getCurrencyInstance. If you need only minor adjustments
to a standard format, you can modify the format returned by
a NumberFormat factory method.
// Always applyPattern after the symbols are set
this.symbols = (DecimalFormatSymbols)symbols.clone();
applyPattern(pattern, false);
|
Methods Summary |
---|
void | adjustForCurrencyDefaultFractionDigits()Adjusts the minimum and maximum fraction digits to values that
are reasonable for the currency's default fraction digits.
Currency currency = symbols.getCurrency();
if (currency == null) {
try {
currency = Currency.getInstance(symbols.getInternationalCurrencySymbol());
} catch (IllegalArgumentException e) {
}
}
if (currency != null) {
int digits = currency.getDefaultFractionDigits();
if (digits != -1) {
int oldMinDigits = getMinimumFractionDigits();
// Common patterns are "#.##", "#.00", "#".
// Try to adjust all of them in a reasonable way.
if (oldMinDigits == getMaximumFractionDigits()) {
setMinimumFractionDigits(digits);
setMaximumFractionDigits(digits);
} else {
setMinimumFractionDigits(Math.min(digits, oldMinDigits));
setMaximumFractionDigits(digits);
}
}
}
| private void | append(java.lang.StringBuffer result, java.lang.String string, FieldDelegate delegate, java.text.FieldPosition[] positions, java.text.Format$Field signAttribute)Appends the String string to result .
delegate is notified of all the
FieldPosition s in positions .
If one of the FieldPosition s in positions
identifies a SIGN attribute, it is mapped to
signAttribute . This is used
to map the SIGN attribute to the EXPONENT
attribute as necessary.
This is used by subformat to add the prefix/suffix.
int start = result.length();
if (string.length() > 0) {
result.append(string);
for (int counter = 0, max = positions.length; counter < max;
counter++) {
FieldPosition fp = positions[counter];
Format.Field attribute = fp.getFieldAttribute();
if (attribute == Field.SIGN) {
attribute = signAttribute;
}
delegate.formatted(attribute, attribute,
start + fp.getBeginIndex(),
start + fp.getEndIndex(), result);
}
}
| private void | appendAffix(java.lang.StringBuffer buffer, java.lang.String affixPattern, java.lang.String expAffix, boolean localized)Appends an affix pattern to the given StringBuffer, quoting special
characters as needed. Uses the internal affix pattern, if that exists,
or the literal affix, if the internal affix pattern is null. The
appended string will generate the same affix pattern (or literal affix)
when passed to toPattern().
if (affixPattern == null) {
appendAffix(buffer, expAffix, localized);
} else {
int i;
for (int pos=0; pos<affixPattern.length(); pos=i) {
i = affixPattern.indexOf(QUOTE, pos);
if (i < 0) {
appendAffix(buffer, affixPattern.substring(pos), localized);
break;
}
if (i > pos) {
appendAffix(buffer, affixPattern.substring(pos, i), localized);
}
char c = affixPattern.charAt(++i);
++i;
if (c == QUOTE) {
buffer.append(c);
// Fall through and append another QUOTE below
} else if (c == CURRENCY_SIGN &&
i<affixPattern.length() &&
affixPattern.charAt(i) == CURRENCY_SIGN) {
++i;
buffer.append(c);
// Fall through and append another CURRENCY_SIGN below
} else if (localized) {
switch (c) {
case PATTERN_PERCENT:
c = symbols.getPercent();
break;
case PATTERN_PER_MILLE:
c = symbols.getPerMill();
break;
case PATTERN_MINUS:
c = symbols.getMinusSign();
break;
}
}
buffer.append(c);
}
}
| private void | appendAffix(java.lang.StringBuffer buffer, java.lang.String affix, boolean localized)Append an affix to the given StringBuffer, using quotes if
there are special characters. Single quotes themselves must be
escaped in either case.
boolean needQuote;
if (localized) {
needQuote = affix.indexOf(symbols.getZeroDigit()) >= 0
|| affix.indexOf(symbols.getGroupingSeparator()) >= 0
|| affix.indexOf(symbols.getDecimalSeparator()) >= 0
|| affix.indexOf(symbols.getPercent()) >= 0
|| affix.indexOf(symbols.getPerMill()) >= 0
|| affix.indexOf(symbols.getDigit()) >= 0
|| affix.indexOf(symbols.getPatternSeparator()) >= 0
|| affix.indexOf(symbols.getMinusSign()) >= 0
|| affix.indexOf(CURRENCY_SIGN) >= 0;
}
else {
needQuote = affix.indexOf(PATTERN_ZERO_DIGIT) >= 0
|| affix.indexOf(PATTERN_GROUPING_SEPARATOR) >= 0
|| affix.indexOf(PATTERN_DECIMAL_SEPARATOR) >= 0
|| affix.indexOf(PATTERN_PERCENT) >= 0
|| affix.indexOf(PATTERN_PER_MILLE) >= 0
|| affix.indexOf(PATTERN_DIGIT) >= 0
|| affix.indexOf(PATTERN_SEPARATOR) >= 0
|| affix.indexOf(PATTERN_MINUS) >= 0
|| affix.indexOf(CURRENCY_SIGN) >= 0;
}
if (needQuote) buffer.append('\'");
if (affix.indexOf('\'") < 0) buffer.append(affix);
else {
for (int j=0; j<affix.length(); ++j) {
char c = affix.charAt(j);
buffer.append(c);
if (c == '\'") buffer.append(c);
}
}
if (needQuote) buffer.append('\'");
| public void | applyLocalizedPattern(java.lang.String pattern)Apply the given pattern to this Format object. The pattern
is assumed to be in a localized notation. A pattern is a
short-hand specification for the various formatting properties.
These properties can also be changed individually through the
various setter methods.
There is no limit to integer digits set
by this routine, since that is the typical end-user desire;
use setMaximumInteger if you want to set a real value.
For negative numbers, use a second pattern, separated by a semicolon
Example "#,#00.0#" -> 1,234.56
This means a minimum of 2 integer digits, 1 fraction digit, and
a maximum of 2 fraction digits.
Example: "#,#00.0#;(#,#00.0#)" for negatives in
parentheses.
In negative patterns, the minimum and maximum counts are ignored;
these are presumed to be set in the positive pattern.
applyPattern(pattern, true);
| public void | applyPattern(java.lang.String pattern)Apply the given pattern to this Format object. A pattern is a
short-hand specification for the various formatting properties.
These properties can also be changed individually through the
various setter methods.
There is no limit to integer digits set
by this routine, since that is the typical end-user desire;
use setMaximumInteger if you want to set a real value.
For negative numbers, use a second pattern, separated by a semicolon
Example "#,#00.0#" -> 1,234.56
This means a minimum of 2 integer digits, 1 fraction digit, and
a maximum of 2 fraction digits.
Example: "#,#00.0#;(#,#00.0#)" for negatives in
parentheses.
In negative patterns, the minimum and maximum counts are ignored;
these are presumed to be set in the positive pattern.
applyPattern(pattern, false);
| private void | applyPattern(java.lang.String pattern, boolean localized)Does the real work of applying a pattern.
char zeroDigit = PATTERN_ZERO_DIGIT;
char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
char decimalSeparator = PATTERN_DECIMAL_SEPARATOR;
char percent = PATTERN_PERCENT;
char perMill = PATTERN_PER_MILLE;
char digit = PATTERN_DIGIT;
char separator = PATTERN_SEPARATOR;
String exponent = PATTERN_EXPONENT;
char minus = PATTERN_MINUS;
if (localized) {
zeroDigit = symbols.getZeroDigit();
groupingSeparator = symbols.getGroupingSeparator();
decimalSeparator = symbols.getDecimalSeparator();
percent = symbols.getPercent();
perMill = symbols.getPerMill();
digit = symbols.getDigit();
separator = symbols.getPatternSeparator();
exponent = symbols.getExponentSeparator();
minus = symbols.getMinusSign();
}
boolean gotNegative = false;
decimalSeparatorAlwaysShown = false;
isCurrencyFormat = false;
useExponentialNotation = false;
// Two variables are used to record the subrange of the pattern
// occupied by phase 1. This is used during the processing of the
// second pattern (the one representing negative numbers) to ensure
// that no deviation exists in phase 1 between the two patterns.
int phaseOneStart = 0;
int phaseOneLength = 0;
int start = 0;
for (int j = 1; j >= 0 && start < pattern.length(); --j) {
boolean inQuote = false;
StringBuffer prefix = new StringBuffer();
StringBuffer suffix = new StringBuffer();
int decimalPos = -1;
int multiplier = 1;
int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0;
byte groupingCount = -1;
// The phase ranges from 0 to 2. Phase 0 is the prefix. Phase 1 is
// the section of the pattern with digits, decimal separator,
// grouping characters. Phase 2 is the suffix. In phases 0 and 2,
// percent, per mille, and currency symbols are recognized and
// translated. The separation of the characters into phases is
// strictly enforced; if phase 1 characters are to appear in the
// suffix, for example, they must be quoted.
int phase = 0;
// The affix is either the prefix or the suffix.
StringBuffer affix = prefix;
for (int pos = start; pos < pattern.length(); ++pos) {
char ch = pattern.charAt(pos);
switch (phase) {
case 0:
case 2:
// Process the prefix / suffix characters
if (inQuote) {
// A quote within quotes indicates either the closing
// quote or two quotes, which is a quote literal. That
// is, we have the second quote in 'do' or 'don''t'.
if (ch == QUOTE) {
if ((pos+1) < pattern.length() &&
pattern.charAt(pos+1) == QUOTE) {
++pos;
affix.append("''"); // 'don''t'
} else {
inQuote = false; // 'do'
}
continue;
}
} else {
// Process unquoted characters seen in prefix or suffix
// phase.
if (ch == digit ||
ch == zeroDigit ||
ch == groupingSeparator ||
ch == decimalSeparator) {
phase = 1;
if (j == 1) {
phaseOneStart = pos;
}
--pos; // Reprocess this character
continue;
} else if (ch == CURRENCY_SIGN) {
// Use lookahead to determine if the currency sign
// is doubled or not.
boolean doubled = (pos + 1) < pattern.length() &&
pattern.charAt(pos + 1) == CURRENCY_SIGN;
if (doubled) { // Skip over the doubled character
++pos;
}
isCurrencyFormat = true;
affix.append(doubled ? "'\u00A4\u00A4" : "'\u00A4");
continue;
} else if (ch == QUOTE) {
// A quote outside quotes indicates either the
// opening quote or two quotes, which is a quote
// literal. That is, we have the first quote in 'do'
// or o''clock.
if (ch == QUOTE) {
if ((pos+1) < pattern.length() &&
pattern.charAt(pos+1) == QUOTE) {
++pos;
affix.append("''"); // o''clock
} else {
inQuote = true; // 'do'
}
continue;
}
} else if (ch == separator) {
// Don't allow separators before we see digit
// characters of phase 1, and don't allow separators
// in the second pattern (j == 0).
if (phase == 0 || j == 0) {
throw new IllegalArgumentException("Unquoted special character '" +
ch + "' in pattern \"" + pattern + '"");
}
start = pos + 1;
pos = pattern.length();
continue;
}
// Next handle characters which are appended directly.
else if (ch == percent) {
if (multiplier != 1) {
throw new IllegalArgumentException("Too many percent/per mille characters in pattern \"" +
pattern + '"");
}
multiplier = 100;
affix.append("'%");
continue;
} else if (ch == perMill) {
if (multiplier != 1) {
throw new IllegalArgumentException("Too many percent/per mille characters in pattern \"" +
pattern + '"");
}
multiplier = 1000;
affix.append("'\u2030");
continue;
} else if (ch == minus) {
affix.append("'-");
continue;
}
}
// Note that if we are within quotes, or if this is an
// unquoted, non-special character, then we usually fall
// through to here.
affix.append(ch);
break;
case 1:
// Phase one must be identical in the two sub-patterns. We
// enforce this by doing a direct comparison. While
// processing the first sub-pattern, we just record its
// length. While processing the second, we compare
// characters.
if (j == 1) {
++phaseOneLength;
} else {
if (--phaseOneLength == 0) {
phase = 2;
affix = suffix;
}
continue;
}
// Process the digits, decimal, and grouping characters. We
// record five pieces of information. We expect the digits
// to occur in the pattern ####0000.####, and we record the
// number of left digits, zero (central) digits, and right
// digits. The position of the last grouping character is
// recorded (should be somewhere within the first two blocks
// of characters), as is the position of the decimal point,
// if any (should be in the zero digits). If there is no
// decimal point, then there should be no right digits.
if (ch == digit) {
if (zeroDigitCount > 0) {
++digitRightCount;
} else {
++digitLeftCount;
}
if (groupingCount >= 0 && decimalPos < 0) {
++groupingCount;
}
} else if (ch == zeroDigit) {
if (digitRightCount > 0) {
throw new IllegalArgumentException("Unexpected '0' in pattern \"" +
pattern + '"");
}
++zeroDigitCount;
if (groupingCount >= 0 && decimalPos < 0) {
++groupingCount;
}
} else if (ch == groupingSeparator) {
groupingCount = 0;
} else if (ch == decimalSeparator) {
if (decimalPos >= 0) {
throw new IllegalArgumentException("Multiple decimal separators in pattern \"" +
pattern + '"");
}
decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
} else if (pattern.regionMatches(pos, exponent, 0, exponent.length())){
if (useExponentialNotation) {
throw new IllegalArgumentException("Multiple exponential " +
"symbols in pattern \"" + pattern + '"");
}
useExponentialNotation = true;
minExponentDigits = 0;
// Use lookahead to parse out the exponential part
// of the pattern, then jump into phase 2.
pos = pos+exponent.length();
while (pos < pattern.length() &&
pattern.charAt(pos) == zeroDigit) {
++minExponentDigits;
++phaseOneLength;
++pos;
}
if ((digitLeftCount + zeroDigitCount) < 1 ||
minExponentDigits < 1) {
throw new IllegalArgumentException("Malformed exponential " +
"pattern \"" + pattern + '"");
}
// Transition to phase 2
phase = 2;
affix = suffix;
--pos;
continue;
} else {
phase = 2;
affix = suffix;
--pos;
--phaseOneLength;
continue;
}
break;
}
}
// Handle patterns with no '0' pattern character. These patterns
// are legal, but must be interpreted. "##.###" -> "#0.###".
// ".###" -> ".0##".
/* We allow patterns of the form "####" to produce a zeroDigitCount
* of zero (got that?); although this seems like it might make it
* possible for format() to produce empty strings, format() checks
* for this condition and outputs a zero digit in this situation.
* Having a zeroDigitCount of zero yields a minimum integer digits
* of zero, which allows proper round-trip patterns. That is, we
* don't want "#" to become "#0" when toPattern() is called (even
* though that's what it really is, semantically).
*/
if (zeroDigitCount == 0 && digitLeftCount > 0 && decimalPos >= 0) {
// Handle "###.###" and "###." and ".###"
int n = decimalPos;
if (n == 0) { // Handle ".###"
++n;
}
digitRightCount = digitLeftCount - n;
digitLeftCount = n - 1;
zeroDigitCount = 1;
}
// Do syntax checking on the digits.
if ((decimalPos < 0 && digitRightCount > 0) ||
(decimalPos >= 0 && (decimalPos < digitLeftCount ||
decimalPos > (digitLeftCount + zeroDigitCount))) ||
groupingCount == 0 || inQuote) {
throw new IllegalArgumentException("Malformed pattern \"" +
pattern + '"");
}
if (j == 1) {
posPrefixPattern = prefix.toString();
posSuffixPattern = suffix.toString();
negPrefixPattern = posPrefixPattern; // assume these for now
negSuffixPattern = posSuffixPattern;
int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
/* The effectiveDecimalPos is the position the decimal is at or
* would be at if there is no decimal. Note that if decimalPos<0,
* then digitTotalCount == digitLeftCount + zeroDigitCount.
*/
int effectiveDecimalPos = decimalPos >= 0 ?
decimalPos : digitTotalCount;
setMinimumIntegerDigits(effectiveDecimalPos - digitLeftCount);
setMaximumIntegerDigits(useExponentialNotation ?
digitLeftCount + getMinimumIntegerDigits() :
MAXIMUM_INTEGER_DIGITS);
setMaximumFractionDigits(decimalPos >= 0 ?
(digitTotalCount - decimalPos) : 0);
setMinimumFractionDigits(decimalPos >= 0 ?
(digitLeftCount + zeroDigitCount - decimalPos) : 0);
setGroupingUsed(groupingCount > 0);
this.groupingSize = (groupingCount > 0) ? groupingCount : 0;
this.multiplier = multiplier;
setDecimalSeparatorAlwaysShown(decimalPos == 0 ||
decimalPos == digitTotalCount);
} else {
negPrefixPattern = prefix.toString();
negSuffixPattern = suffix.toString();
gotNegative = true;
}
}
if (pattern.length() == 0) {
posPrefixPattern = posSuffixPattern = "";
setMinimumIntegerDigits(0);
setMaximumIntegerDigits(MAXIMUM_INTEGER_DIGITS);
setMinimumFractionDigits(0);
setMaximumFractionDigits(MAXIMUM_FRACTION_DIGITS);
}
// If there was no negative pattern, or if the negative pattern is
// identical to the positive pattern, then prepend the minus sign to
// the positive pattern to form the negative pattern.
if (!gotNegative ||
(negPrefixPattern.equals(posPrefixPattern)
&& negSuffixPattern.equals(posSuffixPattern))) {
negSuffixPattern = posSuffixPattern;
negPrefixPattern = "'-" + posPrefixPattern;
}
expandAffixes();
| public java.lang.Object | clone()Standard override; no change in semantics.
try {
DecimalFormat other = (DecimalFormat) super.clone();
other.symbols = (DecimalFormatSymbols) symbols.clone();
other.digitList = (DigitList) digitList.clone();
return other;
} catch (Exception e) {
throw new InternalError();
}
| public boolean | equals(java.lang.Object obj)Overrides equals
if (obj == null) return false;
if (!super.equals(obj)) return false; // super does class check
DecimalFormat other = (DecimalFormat) obj;
return ((posPrefixPattern == other.posPrefixPattern &&
positivePrefix.equals(other.positivePrefix))
|| (posPrefixPattern != null &&
posPrefixPattern.equals(other.posPrefixPattern)))
&& ((posSuffixPattern == other.posSuffixPattern &&
positiveSuffix.equals(other.positiveSuffix))
|| (posSuffixPattern != null &&
posSuffixPattern.equals(other.posSuffixPattern)))
&& ((negPrefixPattern == other.negPrefixPattern &&
negativePrefix.equals(other.negativePrefix))
|| (negPrefixPattern != null &&
negPrefixPattern.equals(other.negPrefixPattern)))
&& ((negSuffixPattern == other.negSuffixPattern &&
negativeSuffix.equals(other.negativeSuffix))
|| (negSuffixPattern != null &&
negSuffixPattern.equals(other.negSuffixPattern)))
&& multiplier == other.multiplier
&& groupingSize == other.groupingSize
&& decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown
&& parseBigDecimal == other.parseBigDecimal
&& useExponentialNotation == other.useExponentialNotation
&& (!useExponentialNotation ||
minExponentDigits == other.minExponentDigits)
&& maximumIntegerDigits == other.maximumIntegerDigits
&& minimumIntegerDigits == other.minimumIntegerDigits
&& maximumFractionDigits == other.maximumFractionDigits
&& minimumFractionDigits == other.minimumFractionDigits
&& roundingMode == other.roundingMode
&& symbols.equals(other.symbols);
| private java.lang.String | expandAffix(java.lang.String pattern, java.lang.StringBuffer buffer)Expand an affix pattern into an affix string. All characters in the
pattern are literal unless prefixed by QUOTE. The following characters
after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
PATTERN_MINUS, and CURRENCY_SIGN. If CURRENCY_SIGN is doubled (QUOTE +
CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 4217
currency code. Any other character after a QUOTE represents itself.
QUOTE must be followed by another character; QUOTE may not occur by
itself at the end of the pattern.
buffer.setLength(0);
for (int i=0; i<pattern.length(); ) {
char c = pattern.charAt(i++);
if (c == QUOTE) {
c = pattern.charAt(i++);
switch (c) {
case CURRENCY_SIGN:
if (i<pattern.length() &&
pattern.charAt(i) == CURRENCY_SIGN) {
++i;
buffer.append(symbols.getInternationalCurrencySymbol());
} else {
buffer.append(symbols.getCurrencySymbol());
}
continue;
case PATTERN_PERCENT:
c = symbols.getPercent();
break;
case PATTERN_PER_MILLE:
c = symbols.getPerMill();
break;
case PATTERN_MINUS:
c = symbols.getMinusSign();
break;
}
}
buffer.append(c);
}
return buffer.toString();
| private java.text.FieldPosition[] | expandAffix(java.lang.String pattern)Expand an affix pattern into an array of FieldPositions describing
how the pattern would be expanded.
All characters in the
pattern are literal unless prefixed by QUOTE. The following characters
after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
PATTERN_MINUS, and CURRENCY_SIGN. If CURRENCY_SIGN is doubled (QUOTE +
CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 4217
currency code. Any other character after a QUOTE represents itself.
QUOTE must be followed by another character; QUOTE may not occur by
itself at the end of the pattern.
ArrayList positions = null;
int stringIndex = 0;
for (int i=0; i<pattern.length(); ) {
char c = pattern.charAt(i++);
if (c == QUOTE) {
int field = -1;
Format.Field fieldID = null;
c = pattern.charAt(i++);
switch (c) {
case CURRENCY_SIGN:
String string;
if (i<pattern.length() &&
pattern.charAt(i) == CURRENCY_SIGN) {
++i;
string = symbols.getInternationalCurrencySymbol();
} else {
string = symbols.getCurrencySymbol();
}
if (string.length() > 0) {
if (positions == null) {
positions = new ArrayList(2);
}
FieldPosition fp = new FieldPosition(Field.CURRENCY);
fp.setBeginIndex(stringIndex);
fp.setEndIndex(stringIndex + string.length());
positions.add(fp);
stringIndex += string.length();
}
continue;
case PATTERN_PERCENT:
c = symbols.getPercent();
field = -1;
fieldID = Field.PERCENT;
break;
case PATTERN_PER_MILLE:
c = symbols.getPerMill();
field = -1;
fieldID = Field.PERMILLE;
break;
case PATTERN_MINUS:
c = symbols.getMinusSign();
field = -1;
fieldID = Field.SIGN;
break;
}
if (fieldID != null) {
if (positions == null) {
positions = new ArrayList(2);
}
FieldPosition fp = new FieldPosition(fieldID, field);
fp.setBeginIndex(stringIndex);
fp.setEndIndex(stringIndex + 1);
positions.add(fp);
}
}
stringIndex++;
}
if (positions != null) {
return (FieldPosition[])positions.toArray(EmptyFieldPositionArray);
}
return EmptyFieldPositionArray;
| private void | expandAffixes()Expand the affix pattern strings into the expanded affix strings. If any
affix pattern string is null, do not expand it. This method should be
called any time the symbols or the affix patterns change in order to keep
the expanded affix strings up to date.
// Reuse one StringBuffer for better performance
StringBuffer buffer = new StringBuffer();
if (posPrefixPattern != null) {
positivePrefix = expandAffix(posPrefixPattern, buffer);
positivePrefixFieldPositions = null;
}
if (posSuffixPattern != null) {
positiveSuffix = expandAffix(posSuffixPattern, buffer);
positiveSuffixFieldPositions = null;
}
if (negPrefixPattern != null) {
negativePrefix = expandAffix(negPrefixPattern, buffer);
negativePrefixFieldPositions = null;
}
if (negSuffixPattern != null) {
negativeSuffix = expandAffix(negSuffixPattern, buffer);
negativeSuffixFieldPositions = null;
}
| private java.lang.StringBuffer | format(java.math.BigDecimal number, java.lang.StringBuffer result, FieldDelegate delegate)Formats a BigDecimal to produce a string.
if (multiplier != 1) {
number = number.multiply(getBigDecimalMultiplier());
}
boolean isNegative = number.signum() == -1;
if (isNegative) {
number = number.negate();
}
synchronized(digitList) {
int maxIntDigits = getMaximumIntegerDigits();
int minIntDigits = getMinimumIntegerDigits();
int maxFraDigits = getMaximumFractionDigits();
int minFraDigits = getMinimumFractionDigits();
int maximumDigits = maxIntDigits + maxFraDigits;
digitList.set(isNegative, number, useExponentialNotation ?
((maximumDigits < 0) ? Integer.MAX_VALUE : maximumDigits) :
maxFraDigits, !useExponentialNotation);
return subformat(result, delegate, isNegative, false,
maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
}
| private java.lang.StringBuffer | format(java.math.BigInteger number, java.lang.StringBuffer result, java.text.FieldPosition fieldPosition)Format a BigInteger to produce a string.
fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0);
return format(number, result, fieldPosition.getFieldDelegate(), false);
| private java.lang.StringBuffer | format(java.math.BigInteger number, java.lang.StringBuffer result, FieldDelegate delegate, boolean formatLong)Format a BigInteger to produce a string.
if (multiplier != 1) {
number = number.multiply(getBigIntegerMultiplier());
}
boolean isNegative = number.signum() == -1;
if (isNegative) {
number = number.negate();
}
synchronized(digitList) {
int maxIntDigits, minIntDigits, maxFraDigits, minFraDigits, maximumDigits;
if (formatLong) {
maxIntDigits = super.getMaximumIntegerDigits();
minIntDigits = super.getMinimumIntegerDigits();
maxFraDigits = super.getMaximumFractionDigits();
minFraDigits = super.getMinimumFractionDigits();
maximumDigits = maxIntDigits + maxFraDigits;
} else {
maxIntDigits = getMaximumIntegerDigits();
minIntDigits = getMinimumIntegerDigits();
maxFraDigits = getMaximumFractionDigits();
minFraDigits = getMinimumFractionDigits();
maximumDigits = maxIntDigits + maxFraDigits;
if (maximumDigits < 0) {
maximumDigits = Integer.MAX_VALUE;
}
}
digitList.set(isNegative, number,
useExponentialNotation ? maximumDigits : 0);
return subformat(result, delegate, isNegative, true,
maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
}
| public final java.lang.StringBuffer | format(java.lang.Object number, java.lang.StringBuffer toAppendTo, java.text.FieldPosition pos)Formats a number and appends the resulting text to the given string
buffer.
The number can be of any subclass of {@link java.lang.Number}.
This implementation uses the maximum precision permitted.
if (number instanceof Long || number instanceof Integer ||
number instanceof Short || number instanceof Byte ||
number instanceof AtomicInteger ||
number instanceof AtomicLong ||
(number instanceof BigInteger &&
((BigInteger)number).bitLength () < 64)) {
return format(((Number)number).longValue(), toAppendTo, pos);
} else if (number instanceof BigDecimal) {
return format((BigDecimal)number, toAppendTo, pos);
} else if (number instanceof BigInteger) {
return format((BigInteger)number, toAppendTo, pos);
} else if (number instanceof Number) {
return format(((Number)number).doubleValue(), toAppendTo, pos);
} else {
throw new IllegalArgumentException("Cannot format given Object as a Number");
}
| public java.lang.StringBuffer | format(double number, java.lang.StringBuffer result, java.text.FieldPosition fieldPosition)Formats a double to produce a string.
fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0);
return format(number, result, fieldPosition.getFieldDelegate());
| private java.lang.StringBuffer | format(double number, java.lang.StringBuffer result, FieldDelegate delegate)Formats a double to produce a string.
if (Double.isNaN(number) ||
(Double.isInfinite(number) && multiplier == 0)) {
int iFieldStart = result.length();
result.append(symbols.getNaN());
delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
iFieldStart, result.length(), result);
return result;
}
/* Detecting whether a double is negative is easy with the exception of
* the value -0.0. This is a double which has a zero mantissa (and
* exponent), but a negative sign bit. It is semantically distinct from
* a zero with a positive sign bit, and this distinction is important
* to certain kinds of computations. However, it's a little tricky to
* detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you may
* ask, does it behave distinctly from +0.0? Well, 1/(-0.0) ==
* -Infinity. Proper detection of -0.0 is needed to deal with the
* issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
*/
boolean isNegative = ((number < 0.0) || (number == 0.0 && 1/number < 0.0)) ^ (multiplier < 0);
if (multiplier != 1) {
number *= multiplier;
}
if (Double.isInfinite(number)) {
if (isNegative) {
append(result, negativePrefix, delegate,
getNegativePrefixFieldPositions(), Field.SIGN);
} else {
append(result, positivePrefix, delegate,
getPositivePrefixFieldPositions(), Field.SIGN);
}
int iFieldStart = result.length();
result.append(symbols.getInfinity());
delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
iFieldStart, result.length(), result);
if (isNegative) {
append(result, negativeSuffix, delegate,
getNegativeSuffixFieldPositions(), Field.SIGN);
} else {
append(result, positiveSuffix, delegate,
getPositiveSuffixFieldPositions(), Field.SIGN);
}
return result;
}
if (isNegative) {
number = -number;
}
// at this point we are guaranteed a nonnegative finite number.
assert(number >= 0 && !Double.isInfinite(number));
synchronized(digitList) {
int maxIntDigits = super.getMaximumIntegerDigits();
int minIntDigits = super.getMinimumIntegerDigits();
int maxFraDigits = super.getMaximumFractionDigits();
int minFraDigits = super.getMinimumFractionDigits();
digitList.set(isNegative, number, useExponentialNotation ?
maxIntDigits + maxFraDigits : maxFraDigits,
!useExponentialNotation);
return subformat(result, delegate, isNegative, false,
maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
}
| public java.lang.StringBuffer | format(long number, java.lang.StringBuffer result, java.text.FieldPosition fieldPosition)Format a long to produce a string.
fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0);
return format(number, result, fieldPosition.getFieldDelegate());
| private java.lang.StringBuffer | format(long number, java.lang.StringBuffer result, FieldDelegate delegate)Format a long to produce a string.
boolean isNegative = (number < 0);
if (isNegative) {
number = -number;
}
// In general, long values always represent real finite numbers, so
// we don't have to check for +/- Infinity or NaN. However, there
// is one case we have to be careful of: The multiplier can push
// a number near MIN_VALUE or MAX_VALUE outside the legal range. We
// check for this before multiplying, and if it happens we use
// BigInteger instead.
boolean useBigInteger = false;
if (number < 0) { // This can only happen if number == Long.MIN_VALUE.
if (multiplier != 0) {
useBigInteger = true;
}
} else if (multiplier != 1 && multiplier != 0) {
long cutoff = Long.MAX_VALUE / multiplier;
if (cutoff < 0) {
cutoff = -cutoff;
}
useBigInteger = (number > cutoff);
}
if (useBigInteger) {
if (isNegative) {
number = -number;
}
BigInteger bigIntegerValue = BigInteger.valueOf(number);
return format(bigIntegerValue, result, delegate, true);
}
number *= multiplier;
if (number == 0) {
isNegative = false;
} else {
if (multiplier < 0) {
number = -number;
isNegative = !isNegative;
}
}
synchronized(digitList) {
int maxIntDigits = super.getMaximumIntegerDigits();
int minIntDigits = super.getMinimumIntegerDigits();
int maxFraDigits = super.getMaximumFractionDigits();
int minFraDigits = super.getMinimumFractionDigits();
digitList.set(isNegative, number,
useExponentialNotation ? maxIntDigits + maxFraDigits : 0);
return subformat(result, delegate, isNegative, true,
maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
}
| private java.lang.StringBuffer | format(java.math.BigDecimal number, java.lang.StringBuffer result, java.text.FieldPosition fieldPosition)Formats a BigDecimal to produce a string.
fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0);
return format(number, result, fieldPosition.getFieldDelegate());
| public java.text.AttributedCharacterIterator | formatToCharacterIterator(java.lang.Object obj)Formats an Object producing an AttributedCharacterIterator .
You can use the returned AttributedCharacterIterator
to build the resulting String, as well as to determine information
about the resulting String.
Each attribute key of the AttributedCharacterIterator will be of type
NumberFormat.Field , with the attribute value being the
same as the attribute key.
CharacterIteratorFieldDelegate delegate =
new CharacterIteratorFieldDelegate();
StringBuffer sb = new StringBuffer();
if (obj instanceof Double || obj instanceof Float) {
format(((Number)obj).doubleValue(), sb, delegate);
} else if (obj instanceof Long || obj instanceof Integer ||
obj instanceof Short || obj instanceof Byte ||
obj instanceof AtomicInteger || obj instanceof AtomicLong) {
format(((Number)obj).longValue(), sb, delegate);
} else if (obj instanceof BigDecimal) {
format((BigDecimal)obj, sb, delegate);
} else if (obj instanceof BigInteger) {
format((BigInteger)obj, sb, delegate, false);
} else if (obj == null) {
throw new NullPointerException(
"formatToCharacterIterator must be passed non-null object");
} else {
throw new IllegalArgumentException(
"Cannot format given Object as a Number");
}
return delegate.getIterator(sb.toString());
| private java.math.BigDecimal | getBigDecimalMultiplier()Return a BigDecimal multiplier.
if (bigDecimalMultiplier == null) {
bigDecimalMultiplier = new BigDecimal(multiplier);
}
return bigDecimalMultiplier;
| private java.math.BigInteger | getBigIntegerMultiplier()Return a BigInteger multiplier.
if (bigIntegerMultiplier == null) {
bigIntegerMultiplier = BigInteger.valueOf(multiplier);
}
return bigIntegerMultiplier;
| public java.util.Currency | getCurrency()Gets the currency used by this decimal format when formatting
currency values.
The currency is obtained by calling
{@link DecimalFormatSymbols#getCurrency DecimalFormatSymbols.getCurrency}
on this number format's symbols.
return symbols.getCurrency();
| public java.text.DecimalFormatSymbols | getDecimalFormatSymbols()Returns a copy of the decimal format symbols, which is generally not
changed by the programmer or user.
try {
// don't allow multiple references
return (DecimalFormatSymbols) symbols.clone();
} catch (Exception foo) {
return null; // should never happen
}
| public int | getGroupingSize()Return the grouping size. Grouping size is the number of digits between
grouping separators in the integer portion of a number. For example,
in the number "123,456.78", the grouping size is 3.
return groupingSize;
| public int | getMaximumFractionDigits()Gets the maximum number of digits allowed in the fraction portion of a
number.
For formatting numbers other than BigInteger and
BigDecimal objects, the lower of the return value and
340 is used.
return maximumFractionDigits;
| public int | getMaximumIntegerDigits()Gets the maximum number of digits allowed in the integer portion of a
number.
For formatting numbers other than BigInteger and
BigDecimal objects, the lower of the return value and
309 is used.
return maximumIntegerDigits;
| public int | getMinimumFractionDigits()Gets the minimum number of digits allowed in the fraction portion of a
number.
For formatting numbers other than BigInteger and
BigDecimal objects, the lower of the return value and
340 is used.
return minimumFractionDigits;
| public int | getMinimumIntegerDigits()Gets the minimum number of digits allowed in the integer portion of a
number.
For formatting numbers other than BigInteger and
BigDecimal objects, the lower of the return value and
309 is used.
return minimumIntegerDigits;
| public int | getMultiplier()Gets the multiplier for use in percent, per mille, and similar
formats.
return multiplier;
| public java.lang.String | getNegativePrefix()Get the negative prefix.
Examples: -123, ($123) (with negative suffix), sFr-123
return negativePrefix;
| private java.text.FieldPosition[] | getNegativePrefixFieldPositions()Returns the FieldPositions of the fields in the prefix used for
negative numbers. This is not used if the user has explicitly set
a negative prefix via setNegativePrefix . This is
lazily created.
if (negativePrefixFieldPositions == null) {
if (negPrefixPattern != null) {
negativePrefixFieldPositions = expandAffix(negPrefixPattern);
}
else {
negativePrefixFieldPositions = EmptyFieldPositionArray;
}
}
return negativePrefixFieldPositions;
| public java.lang.String | getNegativeSuffix()Get the negative suffix.
Examples: -123%, ($123) (with positive suffixes)
return negativeSuffix;
| private java.text.FieldPosition[] | getNegativeSuffixFieldPositions()Returns the FieldPositions of the fields in the suffix used for
negative numbers. This is not used if the user has explicitly set
a negative suffix via setNegativeSuffix . This is
lazily created.
if (negativeSuffixFieldPositions == null) {
if (negSuffixPattern != null) {
negativeSuffixFieldPositions = expandAffix(negSuffixPattern);
}
else {
negativeSuffixFieldPositions = EmptyFieldPositionArray;
}
}
return negativeSuffixFieldPositions;
| public java.lang.String | getPositivePrefix()Get the positive prefix.
Examples: +123, $123, sFr123
return positivePrefix;
| private java.text.FieldPosition[] | getPositivePrefixFieldPositions()Returns the FieldPositions of the fields in the prefix used for
positive numbers. This is not used if the user has explicitly set
a positive prefix via setPositivePrefix . This is
lazily created.
if (positivePrefixFieldPositions == null) {
if (posPrefixPattern != null) {
positivePrefixFieldPositions = expandAffix(posPrefixPattern);
}
else {
positivePrefixFieldPositions = EmptyFieldPositionArray;
}
}
return positivePrefixFieldPositions;
| public java.lang.String | getPositiveSuffix()Get the positive suffix.
Example: 123%
return positiveSuffix;
| private java.text.FieldPosition[] | getPositiveSuffixFieldPositions()Returns the FieldPositions of the fields in the suffix used for
positive numbers. This is not used if the user has explicitly set
a positive suffix via setPositiveSuffix . This is
lazily created.
if (positiveSuffixFieldPositions == null) {
if (posSuffixPattern != null) {
positiveSuffixFieldPositions = expandAffix(posSuffixPattern);
}
else {
positiveSuffixFieldPositions = EmptyFieldPositionArray;
}
}
return positiveSuffixFieldPositions;
| public java.math.RoundingMode | getRoundingMode()Gets the {@link java.math.RoundingMode} used in this DecimalFormat.
return roundingMode;
| public int | hashCode()Overrides hashCode
return super.hashCode() * 37 + positivePrefix.hashCode();
// just enough fields for a reasonable distribution
| public boolean | isDecimalSeparatorAlwaysShown()Allows you to get the behavior of the decimal separator with integers.
(The decimal separator will always appear with decimals.)
Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
return decimalSeparatorAlwaysShown;
| public boolean | isParseBigDecimal()Returns whether the {@link #parse(java.lang.String, java.text.ParsePosition)}
method returns BigDecimal . The default value is false.
return parseBigDecimal;
| public java.lang.Number | parse(java.lang.String text, java.text.ParsePosition pos)Parses text from a string to produce a Number .
The method attempts to parse text starting at the index given by
pos .
If parsing succeeds, then the index of pos is updated
to the index after the last character used (parsing does not necessarily
use all characters up to the end of the string), and the parsed
number is returned. The updated pos can be used to
indicate the starting point for the next call to this method.
If an error occurs, then the index of pos is not
changed, the error index of pos is set to the index of
the character where the error occurred, and null is returned.
The subclass returned depends on the value of {@link #isParseBigDecimal}
as well as on the string being parsed.
DecimalFormat parses all Unicode characters that represent
decimal digits, as defined by Character.digit() . In
addition, DecimalFormat also recognizes as digits the ten
consecutive characters starting with the localized zero digit defined in
the DecimalFormatSymbols object.
// special case NaN
if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols.getNaN().length())) {
pos.index = pos.index + symbols.getNaN().length();
return new Double(Double.NaN);
}
boolean[] status = new boolean[STATUS_LENGTH];
if (!subparse(text, pos, positivePrefix, negativePrefix, digitList, false, status)) {
return null;
}
// special case INFINITY
if (status[STATUS_INFINITE]) {
if (status[STATUS_POSITIVE] == (multiplier >= 0)) {
return new Double(Double.POSITIVE_INFINITY);
} else {
return new Double(Double.NEGATIVE_INFINITY);
}
}
if (multiplier == 0) {
if (digitList.isZero()) {
return new Double(Double.NaN);
} else if (status[STATUS_POSITIVE]) {
return new Double(Double.POSITIVE_INFINITY);
} else {
return new Double(Double.NEGATIVE_INFINITY);
}
}
if (isParseBigDecimal()) {
BigDecimal bigDecimalResult = digitList.getBigDecimal();
if (multiplier != 1) {
try {
bigDecimalResult = bigDecimalResult.divide(getBigDecimalMultiplier());
}
catch (ArithmeticException e) { // non-terminating decimal expansion
bigDecimalResult = bigDecimalResult.divide(getBigDecimalMultiplier(), roundingMode);
}
}
if (!status[STATUS_POSITIVE]) {
bigDecimalResult = bigDecimalResult.negate();
}
return bigDecimalResult;
} else {
boolean gotDouble = true;
boolean gotLongMinimum = false;
double doubleResult = 0.0;
long longResult = 0;
// Finally, have DigitList parse the digits into a value.
if (digitList.fitsIntoLong(status[STATUS_POSITIVE], isParseIntegerOnly())) {
gotDouble = false;
longResult = digitList.getLong();
if (longResult < 0) { // got Long.MIN_VALUE
gotLongMinimum = true;
}
} else {
doubleResult = digitList.getDouble();
}
// Divide by multiplier. We have to be careful here not to do
// unneeded conversions between double and long.
if (multiplier != 1) {
if (gotDouble) {
doubleResult /= multiplier;
} else {
// Avoid converting to double if we can
if (longResult % multiplier == 0) {
longResult /= multiplier;
} else {
doubleResult = ((double)longResult) / multiplier;
gotDouble = true;
}
}
}
if (!status[STATUS_POSITIVE] && !gotLongMinimum) {
doubleResult = -doubleResult;
longResult = -longResult;
}
// At this point, if we divided the result by the multiplier, the
// result may fit into a long. We check for this case and return
// a long if possible.
// We must do this AFTER applying the negative (if appropriate)
// in order to handle the case of LONG_MIN; otherwise, if we do
// this with a positive value -LONG_MIN, the double is > 0, but
// the long is < 0. We also must retain a double in the case of
// -0.0, which will compare as == to a long 0 cast to a double
// (bug 4162852).
if (multiplier != 1 && gotDouble) {
longResult = (long)doubleResult;
gotDouble = ((doubleResult != (double)longResult) ||
(doubleResult == 0.0 && 1/doubleResult < 0.0)) &&
!isParseIntegerOnly();
}
return gotDouble ?
(Number)new Double(doubleResult) : (Number)new Long(longResult);
}
| private void | readObject(java.io.ObjectInputStream stream)Reads the default serializable fields from the stream and performs
validations and adjustments for older serialized versions. The
validations and adjustments are:
-
Verify that the superclass's digit count fields correctly reflect
the limits imposed on formatting numbers other than
BigInteger and BigDecimal objects. These
limits are stored in the superclass for serialization compatibility
with older versions, while the limits for BigInteger and
BigDecimal objects are kept in this class.
If, in the superclass, the minimum or maximum integer digit count is
larger than DOUBLE_INTEGER_DIGITS or if the minimum or
maximum fraction digit count is larger than
DOUBLE_FRACTION_DIGITS , then the stream data is invalid
and this method throws an InvalidObjectException .
-
If
serialVersionOnStream is less than 4, initialize
roundingMode to {@link java.math.RoundingMode#HALF_EVEN
RoundingMode.HALF_EVEN}. This field is new with version 4.
-
If
serialVersionOnStream is less than 3, then call
the setters for the minimum and maximum integer and fraction digits with
the values of the corresponding superclass getters to initialize the
fields in this class. The fields in this class are new with version 3.
-
If
serialVersionOnStream is less than 1, indicating that
the stream was written by JDK 1.1, initialize
useExponentialNotation
to false, since it was not present in JDK 1.1.
-
Set
serialVersionOnStream to the maximum allowed value so
that default serialization will work properly if this object is streamed
out again.
Stream versions older than 2 will not have the affix pattern variables
posPrefixPattern etc. As a result, they will be initialized
to null , which means the affix strings will be taken as
literal values. This is exactly what we want, since that corresponds to
the pre-version-2 behavior.
stream.defaultReadObject();
digitList = new DigitList();
if (serialVersionOnStream < 4) {
setRoundingMode(RoundingMode.HALF_EVEN);
}
// We only need to check the maximum counts because NumberFormat
// .readObject has already ensured that the maximum is greater than the
// minimum count.
if (super.getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||
super.getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
throw new InvalidObjectException("Digit count out of range");
}
if (serialVersionOnStream < 3) {
setMaximumIntegerDigits(super.getMaximumIntegerDigits());
setMinimumIntegerDigits(super.getMinimumIntegerDigits());
setMaximumFractionDigits(super.getMaximumFractionDigits());
setMinimumFractionDigits(super.getMinimumFractionDigits());
}
if (serialVersionOnStream < 1) {
// Didn't have exponential fields
useExponentialNotation = false;
}
serialVersionOnStream = currentSerialVersion;
| public void | setCurrency(java.util.Currency currency)Sets the currency used by this number format when formatting
currency values. This does not update the minimum or maximum
number of fraction digits used by the number format.
The currency is set by calling
{@link DecimalFormatSymbols#setCurrency DecimalFormatSymbols.setCurrency}
on this number format's symbols.
if (currency != symbols.getCurrency()) {
symbols.setCurrency(currency);
if (isCurrencyFormat) {
expandAffixes();
}
}
| public void | setDecimalFormatSymbols(java.text.DecimalFormatSymbols newSymbols)Sets the decimal format symbols, which is generally not changed
by the programmer or user.
try {
// don't allow multiple references
symbols = (DecimalFormatSymbols) newSymbols.clone();
expandAffixes();
} catch (Exception foo) {
// should never happen
}
| public void | setDecimalSeparatorAlwaysShown(boolean newValue)Allows you to set the behavior of the decimal separator with integers.
(The decimal separator will always appear with decimals.)
Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
decimalSeparatorAlwaysShown = newValue;
| public void | setGroupingSize(int newValue)Set the grouping size. Grouping size is the number of digits between
grouping separators in the integer portion of a number. For example,
in the number "123,456.78", the grouping size is 3.
The value passed in is converted to a byte, which may lose information.
groupingSize = (byte)newValue;
| public void | setMaximumFractionDigits(int newValue)Sets the maximum number of digits allowed in the fraction portion of a
number.
For formatting numbers other than BigInteger and
BigDecimal objects, the lower of newValue and
340 is used. Negative input values are replaced with 0.
maximumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS);
super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
DOUBLE_FRACTION_DIGITS : maximumFractionDigits);
if (minimumFractionDigits > maximumFractionDigits) {
minimumFractionDigits = maximumFractionDigits;
super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
DOUBLE_FRACTION_DIGITS : minimumFractionDigits);
}
| public void | setMaximumIntegerDigits(int newValue)Sets the maximum number of digits allowed in the integer portion of a
number.
For formatting numbers other than BigInteger and
BigDecimal objects, the lower of newValue and
309 is used. Negative input values are replaced with 0.
maximumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS);
super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
DOUBLE_INTEGER_DIGITS : maximumIntegerDigits);
if (minimumIntegerDigits > maximumIntegerDigits) {
minimumIntegerDigits = maximumIntegerDigits;
super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
DOUBLE_INTEGER_DIGITS : minimumIntegerDigits);
}
| public void | setMinimumFractionDigits(int newValue)Sets the minimum number of digits allowed in the fraction portion of a
number.
For formatting numbers other than BigInteger and
BigDecimal objects, the lower of newValue and
340 is used. Negative input values are replaced with 0.
minimumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS);
super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
DOUBLE_FRACTION_DIGITS : minimumFractionDigits);
if (minimumFractionDigits > maximumFractionDigits) {
maximumFractionDigits = minimumFractionDigits;
super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
DOUBLE_FRACTION_DIGITS : maximumFractionDigits);
}
| public void | setMinimumIntegerDigits(int newValue)Sets the minimum number of digits allowed in the integer portion of a
number.
For formatting numbers other than BigInteger and
BigDecimal objects, the lower of newValue and
309 is used. Negative input values are replaced with 0.
minimumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS);
super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
DOUBLE_INTEGER_DIGITS : minimumIntegerDigits);
if (minimumIntegerDigits > maximumIntegerDigits) {
maximumIntegerDigits = minimumIntegerDigits;
super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
DOUBLE_INTEGER_DIGITS : maximumIntegerDigits);
}
| public void | setMultiplier(int newValue)Sets the multiplier for use in percent, per mille, and similar
formats.
For a percent format, set the multiplier to 100 and the suffixes to
have '%' (for Arabic, use the Arabic percent sign).
For a per mille format, set the multiplier to 1000 and the suffixes to
have '\u2030'.
Example: with multiplier 100, 1.23 is formatted as "123", and
"123" is parsed into 1.23.
multiplier = newValue;
bigDecimalMultiplier = null;
bigIntegerMultiplier = null;
| public void | setNegativePrefix(java.lang.String newValue)Set the negative prefix.
Examples: -123, ($123) (with negative suffix), sFr-123
negativePrefix = newValue;
negPrefixPattern = null;
| public void | setNegativeSuffix(java.lang.String newValue)Set the negative suffix.
Examples: 123%
negativeSuffix = newValue;
negSuffixPattern = null;
| public void | setParseBigDecimal(boolean newValue)Sets whether the {@link #parse(java.lang.String, java.text.ParsePosition)}
method returns BigDecimal .
parseBigDecimal = newValue;
| public void | setPositivePrefix(java.lang.String newValue)Set the positive prefix.
Examples: +123, $123, sFr123
positivePrefix = newValue;
posPrefixPattern = null;
positivePrefixFieldPositions = null;
| public void | setPositiveSuffix(java.lang.String newValue)Set the positive suffix.
Example: 123%
positiveSuffix = newValue;
posSuffixPattern = null;
| public void | setRoundingMode(java.math.RoundingMode roundingMode)Sets the {@link java.math.RoundingMode} used in this DecimalFormat.
if (roundingMode == null) {
throw new NullPointerException();
}
this.roundingMode = roundingMode;
digitList.setRoundingMode(roundingMode);
| private java.lang.StringBuffer | subformat(java.lang.StringBuffer result, FieldDelegate delegate, boolean isNegative, boolean isInteger, int maxIntDigits, int minIntDigits, int maxFraDigits, int minFraDigits)Complete the formatting of a finite number. On entry, the digitList must
be filled in with the correct digits.
// NOTE: This isn't required anymore because DigitList takes care of this.
//
// // The negative of the exponent represents the number of leading
// // zeros between the decimal and the first non-zero digit, for
// // a value < 0.1 (e.g., for 0.00123, -fExponent == 2). If this
// // is more than the maximum fraction digits, then we have an underflow
// // for the printed representation. We recognize this here and set
// // the DigitList representation to zero in this situation.
//
// if (-digitList.decimalAt >= getMaximumFractionDigits())
// {
// digitList.count = 0;
// }
char zero = symbols.getZeroDigit();
int zeroDelta = zero - '0"; // '0' is the DigitList representation of zero
char grouping = symbols.getGroupingSeparator();
char decimal = isCurrencyFormat ?
symbols.getMonetaryDecimalSeparator() :
symbols.getDecimalSeparator();
/* Per bug 4147706, DecimalFormat must respect the sign of numbers which
* format as zero. This allows sensible computations and preserves
* relations such as signum(1/x) = signum(x), where x is +Infinity or
* -Infinity. Prior to this fix, we always formatted zero values as if
* they were positive. Liu 7/6/98.
*/
if (digitList.isZero()) {
digitList.decimalAt = 0; // Normalize
}
if (isNegative) {
append(result, negativePrefix, delegate,
getNegativePrefixFieldPositions(), Field.SIGN);
} else {
append(result, positivePrefix, delegate,
getPositivePrefixFieldPositions(), Field.SIGN);
}
if (useExponentialNotation) {
int iFieldStart = result.length();
int iFieldEnd = -1;
int fFieldStart = -1;
// Minimum integer digits are handled in exponential format by
// adjusting the exponent. For example, 0.01234 with 3 minimum
// integer digits is "123.4E-4".
// Maximum integer digits are interpreted as indicating the
// repeating range. This is useful for engineering notation, in
// which the exponent is restricted to a multiple of 3. For
// example, 0.01234 with 3 maximum integer digits is "12.34e-3".
// If maximum integer digits are > 1 and are larger than
// minimum integer digits, then minimum integer digits are
// ignored.
int exponent = digitList.decimalAt;
int repeat = maxIntDigits;
int minimumIntegerDigits = minIntDigits;
if (repeat > 1 && repeat > minIntDigits) {
// A repeating range is defined; adjust to it as follows.
// If repeat == 3, we have 6,5,4=>3; 3,2,1=>0; 0,-1,-2=>-3;
// -3,-4,-5=>-6, etc. This takes into account that the
// exponent we have here is off by one from what we expect;
// it is for the format 0.MMMMMx10^n.
if (exponent >= 1) {
exponent = ((exponent - 1) / repeat) * repeat;
} else {
// integer division rounds towards 0
exponent = ((exponent - repeat) / repeat) * repeat;
}
minimumIntegerDigits = 1;
} else {
// No repeating range is defined; use minimum integer digits.
exponent -= minimumIntegerDigits;
}
// We now output a minimum number of digits, and more if there
// are more digits, up to the maximum number of digits. We
// place the decimal point after the "integer" digits, which
// are the first (decimalAt - exponent) digits.
int minimumDigits = minIntDigits + minFraDigits;
if (minimumDigits < 0) { // overflow?
minimumDigits = Integer.MAX_VALUE;
}
// The number of integer digits is handled specially if the number
// is zero, since then there may be no digits.
int integerDigits = digitList.isZero() ? minimumIntegerDigits :
digitList.decimalAt - exponent;
if (minimumDigits < integerDigits) {
minimumDigits = integerDigits;
}
int totalDigits = digitList.count;
if (minimumDigits > totalDigits) {
totalDigits = minimumDigits;
}
boolean addedDecimalSeparator = false;
for (int i=0; i<totalDigits; ++i) {
if (i == integerDigits) {
// Record field information for caller.
iFieldEnd = result.length();
result.append(decimal);
addedDecimalSeparator = true;
// Record field information for caller.
fFieldStart = result.length();
}
result.append((i < digitList.count) ?
(char)(digitList.digits[i] + zeroDelta) :
zero);
}
if (decimalSeparatorAlwaysShown && totalDigits == integerDigits) {
// Record field information for caller.
iFieldEnd = result.length();
result.append(decimal);
addedDecimalSeparator = true;
// Record field information for caller.
fFieldStart = result.length();
}
// Record field information
if (iFieldEnd == -1) {
iFieldEnd = result.length();
}
delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
iFieldStart, iFieldEnd, result);
if (addedDecimalSeparator) {
delegate.formatted(Field.DECIMAL_SEPARATOR,
Field.DECIMAL_SEPARATOR,
iFieldEnd, fFieldStart, result);
}
if (fFieldStart == -1) {
fFieldStart = result.length();
}
delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION,
fFieldStart, result.length(), result);
// The exponent is output using the pattern-specified minimum
// exponent digits. There is no maximum limit to the exponent
// digits, since truncating the exponent would result in an
// unacceptable inaccuracy.
int fieldStart = result.length();
result.append(symbols.getExponentSeparator());
delegate.formatted(Field.EXPONENT_SYMBOL, Field.EXPONENT_SYMBOL,
fieldStart, result.length(), result);
// For zero values, we force the exponent to zero. We
// must do this here, and not earlier, because the value
// is used to determine integer digit count above.
if (digitList.isZero()) {
exponent = 0;
}
boolean negativeExponent = exponent < 0;
if (negativeExponent) {
exponent = -exponent;
fieldStart = result.length();
result.append(symbols.getMinusSign());
delegate.formatted(Field.EXPONENT_SIGN, Field.EXPONENT_SIGN,
fieldStart, result.length(), result);
}
digitList.set(negativeExponent, exponent);
int eFieldStart = result.length();
for (int i=digitList.decimalAt; i<minExponentDigits; ++i) {
result.append(zero);
}
for (int i=0; i<digitList.decimalAt; ++i) {
result.append((i < digitList.count) ?
(char)(digitList.digits[i] + zeroDelta) : zero);
}
delegate.formatted(Field.EXPONENT, Field.EXPONENT, eFieldStart,
result.length(), result);
} else {
int iFieldStart = result.length();
// Output the integer portion. Here 'count' is the total
// number of integer digits we will display, including both
// leading zeros required to satisfy getMinimumIntegerDigits,
// and actual digits present in the number.
int count = minIntDigits;
int digitIndex = 0; // Index into digitList.fDigits[]
if (digitList.decimalAt > 0 && count < digitList.decimalAt) {
count = digitList.decimalAt;
}
// Handle the case where getMaximumIntegerDigits() is smaller
// than the real number of integer digits. If this is so, we
// output the least significant max integer digits. For example,
// the value 1997 printed with 2 max integer digits is just "97".
if (count > maxIntDigits) {
count = maxIntDigits;
digitIndex = digitList.decimalAt - count;
}
int sizeBeforeIntegerPart = result.length();
for (int i=count-1; i>=0; --i) {
if (i < digitList.decimalAt && digitIndex < digitList.count) {
// Output a real digit
result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
} else {
// Output a leading zero
result.append(zero);
}
// Output grouping separator if necessary. Don't output a
// grouping separator if i==0 though; that's at the end of
// the integer part.
if (isGroupingUsed() && i>0 && (groupingSize != 0) &&
(i % groupingSize == 0)) {
int gStart = result.length();
result.append(grouping);
delegate.formatted(Field.GROUPING_SEPARATOR,
Field.GROUPING_SEPARATOR, gStart,
result.length(), result);
}
}
// Determine whether or not there are any printable fractional
// digits. If we've used up the digits we know there aren't.
boolean fractionPresent = (minFraDigits > 0) ||
(!isInteger && digitIndex < digitList.count);
// If there is no fraction present, and we haven't printed any
// integer digits, then print a zero. Otherwise we won't print
// _any_ digits, and we won't be able to parse this string.
if (!fractionPresent && result.length() == sizeBeforeIntegerPart) {
result.append(zero);
}
delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
iFieldStart, result.length(), result);
// Output the decimal separator if we always do so.
int sStart = result.length();
if (decimalSeparatorAlwaysShown || fractionPresent) {
result.append(decimal);
}
if (sStart != result.length()) {
delegate.formatted(Field.DECIMAL_SEPARATOR,
Field.DECIMAL_SEPARATOR,
sStart, result.length(), result);
}
int fFieldStart = result.length();
for (int i=0; i < maxFraDigits; ++i) {
// Here is where we escape from the loop. We escape if we've
// output the maximum fraction digits (specified in the for
// expression above).
// We also stop when we've output the minimum digits and either:
// we have an integer, so there is no fractional stuff to
// display, or we're out of significant digits.
if (i >= minFraDigits &&
(isInteger || digitIndex >= digitList.count)) {
break;
}
// Output leading fractional zeros. These are zeros that come
// after the decimal but before any significant digits. These
// are only output if abs(number being formatted) < 1.0.
if (-1-i > (digitList.decimalAt-1)) {
result.append(zero);
continue;
}
// Output a digit, if we have any precision left, or a
// zero if we don't. We don't want to output noise digits.
if (!isInteger && digitIndex < digitList.count) {
result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
} else {
result.append(zero);
}
}
// Record field information for caller.
delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION,
fFieldStart, result.length(), result);
}
if (isNegative) {
append(result, negativeSuffix, delegate,
getNegativeSuffixFieldPositions(), Field.SIGN);
}
else {
append(result, positiveSuffix, delegate,
getPositiveSuffixFieldPositions(), Field.SIGN);
}
return result;
| private final boolean | subparse(java.lang.String text, java.text.ParsePosition parsePosition, java.lang.String positivePrefix, java.lang.String negativePrefix, java.text.DigitList digits, boolean isExponent, boolean[] status)Parse the given text into a number. The text is parsed beginning at
parsePosition, until an unparseable character is seen.
int position = parsePosition.index;
int oldStart = parsePosition.index;
int backup;
boolean gotPositive, gotNegative;
// check for positivePrefix; take longest
gotPositive = text.regionMatches(position, positivePrefix, 0,
positivePrefix.length());
gotNegative = text.regionMatches(position, negativePrefix, 0,
negativePrefix.length());
if (gotPositive && gotNegative) {
if (positivePrefix.length() > negativePrefix.length()) {
gotNegative = false;
} else if (positivePrefix.length() < negativePrefix.length()) {
gotPositive = false;
}
}
if (gotPositive) {
position += positivePrefix.length();
} else if (gotNegative) {
position += negativePrefix.length();
} else {
parsePosition.errorIndex = position;
return false;
}
// process digits or Inf, find decimal position
status[STATUS_INFINITE] = false;
if (!isExponent && text.regionMatches(position,symbols.getInfinity(),0,
symbols.getInfinity().length())) {
position += symbols.getInfinity().length();
status[STATUS_INFINITE] = true;
} else {
// We now have a string of digits, possibly with grouping symbols,
// and decimal points. We want to process these into a DigitList.
// We don't want to put a bunch of leading zeros into the DigitList
// though, so we keep track of the location of the decimal point,
// put only significant digits into the DigitList, and adjust the
// exponent as needed.
digits.decimalAt = digits.count = 0;
char zero = symbols.getZeroDigit();
char decimal = isCurrencyFormat ?
symbols.getMonetaryDecimalSeparator() :
symbols.getDecimalSeparator();
char grouping = symbols.getGroupingSeparator();
String exponentString = symbols.getExponentSeparator();
boolean sawDecimal = false;
boolean sawExponent = false;
boolean sawDigit = false;
int exponent = 0; // Set to the exponent value, if any
// We have to track digitCount ourselves, because digits.count will
// pin when the maximum allowable digits is reached.
int digitCount = 0;
backup = -1;
for (; position < text.length(); ++position) {
char ch = text.charAt(position);
/* We recognize all digit ranges, not only the Latin digit range
* '0'..'9'. We do so by using the Character.digit() method,
* which converts a valid Unicode digit to the range 0..9.
*
* The character 'ch' may be a digit. If so, place its value
* from 0 to 9 in 'digit'. First try using the locale digit,
* which may or MAY NOT be a standard Unicode digit range. If
* this fails, try using the standard Unicode digit ranges by
* calling Character.digit(). If this also fails, digit will
* have a value outside the range 0..9.
*/
int digit = ch - zero;
if (digit < 0 || digit > 9) {
digit = Character.digit(ch, 10);
}
if (digit == 0) {
// Cancel out backup setting (see grouping handler below)
backup = -1; // Do this BEFORE continue statement below!!!
sawDigit = true;
// Handle leading zeros
if (digits.count == 0) {
// Ignore leading zeros in integer part of number.
if (!sawDecimal) {
continue;
}
// If we have seen the decimal, but no significant
// digits yet, then we account for leading zeros by
// decrementing the digits.decimalAt into negative
// values.
--digits.decimalAt;
} else {
++digitCount;
digits.append((char)(digit + '0"));
}
} else if (digit > 0 && digit <= 9) { // [sic] digit==0 handled above
sawDigit = true;
++digitCount;
digits.append((char)(digit + '0"));
// Cancel out backup setting (see grouping handler below)
backup = -1;
} else if (!isExponent && ch == decimal) {
// If we're only parsing integers, or if we ALREADY saw the
// decimal, then don't parse this one.
if (isParseIntegerOnly() || sawDecimal) {
break;
}
digits.decimalAt = digitCount; // Not digits.count!
sawDecimal = true;
} else if (!isExponent && ch == grouping && isGroupingUsed()) {
if (sawDecimal) {
break;
}
// Ignore grouping characters, if we are using them, but
// require that they be followed by a digit. Otherwise
// we backup and reprocess them.
backup = position;
} else if (!isExponent && text.regionMatches(position, exponentString, 0, exponentString.length())
&& !sawExponent) {
// Process the exponent by recursively calling this method.
ParsePosition pos = new ParsePosition(position + exponentString.length());
boolean[] stat = new boolean[STATUS_LENGTH];
DigitList exponentDigits = new DigitList();
if (subparse(text, pos, "", Character.toString(symbols.getMinusSign()), exponentDigits, true, stat) &&
exponentDigits.fitsIntoLong(stat[STATUS_POSITIVE], true)) {
position = pos.index; // Advance past the exponent
exponent = (int)exponentDigits.getLong();
if (!stat[STATUS_POSITIVE]) {
exponent = -exponent;
}
sawExponent = true;
}
break; // Whether we fail or succeed, we exit this loop
}
else {
break;
}
}
if (backup != -1) {
position = backup;
}
// If there was no decimal point we have an integer
if (!sawDecimal) {
digits.decimalAt = digitCount; // Not digits.count!
}
// Adjust for exponent, if any
digits.decimalAt += exponent;
// If none of the text string was recognized. For example, parse
// "x" with pattern "#0.00" (return index and error index both 0)
// parse "$" with pattern "$#0.00". (return index 0 and error
// index 1).
if (!sawDigit && digitCount == 0) {
parsePosition.index = oldStart;
parsePosition.errorIndex = oldStart;
return false;
}
}
// check for suffix
if (!isExponent) {
if (gotPositive) {
gotPositive = text.regionMatches(position,positiveSuffix,0,
positiveSuffix.length());
}
if (gotNegative) {
gotNegative = text.regionMatches(position,negativeSuffix,0,
negativeSuffix.length());
}
// if both match, take longest
if (gotPositive && gotNegative) {
if (positiveSuffix.length() > negativeSuffix.length()) {
gotNegative = false;
} else if (positiveSuffix.length() < negativeSuffix.length()) {
gotPositive = false;
}
}
// fail if neither or both
if (gotPositive == gotNegative) {
parsePosition.errorIndex = position;
return false;
}
parsePosition.index = position +
(gotPositive ? positiveSuffix.length() : negativeSuffix.length()); // mark success!
} else {
parsePosition.index = position;
}
status[STATUS_POSITIVE] = gotPositive;
if (parsePosition.index == oldStart) {
parsePosition.errorIndex = position;
return false;
}
return true;
| public java.lang.String | toLocalizedPattern()Synthesizes a localized pattern string that represents the current
state of this Format object.
return toPattern( true );
| public java.lang.String | toPattern()Synthesizes a pattern string that represents the current state
of this Format object.
return toPattern( false );
| private java.lang.String | toPattern(boolean localized)Does the real work of generating a pattern.
StringBuffer result = new StringBuffer();
for (int j = 1; j >= 0; --j) {
if (j == 1)
appendAffix(result, posPrefixPattern, positivePrefix, localized);
else appendAffix(result, negPrefixPattern, negativePrefix, localized);
int i;
int digitCount = useExponentialNotation
? getMaximumIntegerDigits()
: Math.max(groupingSize, getMinimumIntegerDigits())+1;
for (i = digitCount; i > 0; --i) {
if (i != digitCount && isGroupingUsed() && groupingSize != 0 &&
i % groupingSize == 0) {
result.append(localized ? symbols.getGroupingSeparator() :
PATTERN_GROUPING_SEPARATOR);
}
result.append(i <= getMinimumIntegerDigits()
? (localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT)
: (localized ? symbols.getDigit() : PATTERN_DIGIT));
}
if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown)
result.append(localized ? symbols.getDecimalSeparator() :
PATTERN_DECIMAL_SEPARATOR);
for (i = 0; i < getMaximumFractionDigits(); ++i) {
if (i < getMinimumFractionDigits()) {
result.append(localized ? symbols.getZeroDigit() :
PATTERN_ZERO_DIGIT);
} else {
result.append(localized ? symbols.getDigit() :
PATTERN_DIGIT);
}
}
if (useExponentialNotation)
{
result.append(localized ? symbols.getExponentSeparator() :
PATTERN_EXPONENT);
for (i=0; i<minExponentDigits; ++i)
result.append(localized ? symbols.getZeroDigit() :
PATTERN_ZERO_DIGIT);
}
if (j == 1) {
appendAffix(result, posSuffixPattern, positiveSuffix, localized);
if ((negSuffixPattern == posSuffixPattern && // n == p == null
negativeSuffix.equals(positiveSuffix))
|| (negSuffixPattern != null &&
negSuffixPattern.equals(posSuffixPattern))) {
if ((negPrefixPattern != null && posPrefixPattern != null &&
negPrefixPattern.equals("'-" + posPrefixPattern)) ||
(negPrefixPattern == posPrefixPattern && // n == p == null
negativePrefix.equals(symbols.getMinusSign() + positivePrefix)))
break;
}
result.append(localized ? symbols.getPatternSeparator() :
PATTERN_SEPARATOR);
} else appendAffix(result, negSuffixPattern, negativeSuffix, localized);
}
return result.toString();
|
|