Path: blob/master/src/java.base/share/classes/java/text/DecimalFormat.java
41152 views
/*1* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved27* (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved28*29* The original version of this source code and documentation is copyrighted30* and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These31* materials are provided under terms of a License Agreement between Taligent32* and Sun. This technology is protected by multiple US and International33* patents. This notice and attribution to Taligent may not be removed.34* Taligent is a registered trademark of Taligent, Inc.35*36*/3738package java.text;3940import java.io.IOException;41import java.io.InvalidObjectException;42import java.io.ObjectInputStream;43import java.math.BigDecimal;44import java.math.BigInteger;45import java.math.RoundingMode;46import java.text.spi.NumberFormatProvider;47import java.util.ArrayList;48import java.util.Currency;49import java.util.Locale;50import java.util.concurrent.atomic.AtomicInteger;51import java.util.concurrent.atomic.AtomicLong;52import sun.util.locale.provider.LocaleProviderAdapter;53import sun.util.locale.provider.ResourceBundleBasedAdapter;5455/**56* {@code DecimalFormat} is a concrete subclass of57* {@code NumberFormat} that formats decimal numbers. It has a variety of58* features designed to make it possible to parse and format numbers in any59* locale, including support for Western, Arabic, and Indic digits. It also60* supports different kinds of numbers, including integers (123), fixed-point61* numbers (123.4), scientific notation (1.23E4), percentages (12%), and62* currency amounts ($123). All of these can be localized.63*64* <p>To obtain a {@code NumberFormat} for a specific locale, including the65* default locale, call one of {@code NumberFormat}'s factory methods, such66* as {@code getInstance()}. In general, do not call the67* {@code DecimalFormat} constructors directly, since the68* {@code NumberFormat} factory methods may return subclasses other than69* {@code DecimalFormat}. If you need to customize the format object, do70* something like this:71*72* <blockquote><pre>73* NumberFormat f = NumberFormat.getInstance(loc);74* if (f instanceof DecimalFormat) {75* ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);76* }77* </pre></blockquote>78*79* <p>A {@code DecimalFormat} comprises a <em>pattern</em> and a set of80* <em>symbols</em>. The pattern may be set directly using81* {@code applyPattern()}, or indirectly using the API methods. The82* symbols are stored in a {@code DecimalFormatSymbols} object. When using83* the {@code NumberFormat} factory methods, the pattern and symbols are84* read from localized {@code ResourceBundle}s.85*86* <h2>Patterns</h2>87*88* {@code DecimalFormat} patterns have the following syntax:89* <blockquote><pre>90* <i>Pattern:</i>91* <i>PositivePattern</i>92* <i>PositivePattern</i> ; <i>NegativePattern</i>93* <i>PositivePattern:</i>94* <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>95* <i>NegativePattern:</i>96* <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>97* <i>Prefix:</i>98* any Unicode characters except \uFFFE, \uFFFF, and special characters99* <i>Suffix:</i>100* any Unicode characters except \uFFFE, \uFFFF, and special characters101* <i>Number:</i>102* <i>Integer</i> <i>Exponent<sub>opt</sub></i>103* <i>Integer</i> . <i>Fraction</i> <i>Exponent<sub>opt</sub></i>104* <i>Integer:</i>105* <i>MinimumInteger</i>106* #107* # <i>Integer</i>108* # , <i>Integer</i>109* <i>MinimumInteger:</i>110* 0111* 0 <i>MinimumInteger</i>112* 0 , <i>MinimumInteger</i>113* <i>Fraction:</i>114* <i>MinimumFraction<sub>opt</sub></i> <i>OptionalFraction<sub>opt</sub></i>115* <i>MinimumFraction:</i>116* 0 <i>MinimumFraction<sub>opt</sub></i>117* <i>OptionalFraction:</i>118* # <i>OptionalFraction<sub>opt</sub></i>119* <i>Exponent:</i>120* E <i>MinimumExponent</i>121* <i>MinimumExponent:</i>122* 0 <i>MinimumExponent<sub>opt</sub></i>123* </pre></blockquote>124*125* <p>A {@code DecimalFormat} pattern contains a positive and negative126* subpattern, for example, {@code "#,##0.00;(#,##0.00)"}. Each127* subpattern has a prefix, numeric part, and suffix. The negative subpattern128* is optional; if absent, then the positive subpattern prefixed with the129* minus sign ({@code '-' U+002D HYPHEN-MINUS}) is used as the130* negative subpattern. That is, {@code "0.00"} alone is equivalent to131* {@code "0.00;-0.00"}. If there is an explicit negative subpattern, it132* serves only to specify the negative prefix and suffix; the number of digits,133* minimal digits, and other characteristics are all the same as the positive134* pattern. That means that {@code "#,##0.0#;(#)"} produces precisely135* the same behavior as {@code "#,##0.0#;(#,##0.0#)"}.136*137* <p>The prefixes, suffixes, and various symbols used for infinity, digits,138* grouping separators, decimal separators, etc. may be set to arbitrary139* values, and they will appear properly during formatting. However, care must140* be taken that the symbols and strings do not conflict, or parsing will be141* unreliable. For example, either the positive and negative prefixes or the142* suffixes must be distinct for {@code DecimalFormat.parse()} to be able143* to distinguish positive from negative values. (If they are identical, then144* {@code DecimalFormat} will behave as if no negative subpattern was145* specified.) Another example is that the decimal separator and grouping146* separator should be distinct characters, or parsing will be impossible.147*148* <p>The grouping separator is commonly used for thousands, but in some149* countries it separates ten-thousands. The grouping size is a constant number150* of digits between the grouping characters, such as 3 for 100,000,000 or 4 for151* 1,0000,0000. If you supply a pattern with multiple grouping characters, the152* interval between the last one and the end of the integer is the one that is153* used. So {@code "#,##,###,####"} == {@code "######,####"} ==154* {@code "##,####,####"}.155*156* <h3><a id="special_pattern_character">Special Pattern Characters</a></h3>157*158* <p>Many characters in a pattern are taken literally; they are matched during159* parsing and output unchanged during formatting. Special characters, on the160* other hand, stand for other characters, strings, or classes of characters.161* They must be quoted, unless noted otherwise, if they are to appear in the162* prefix or suffix as literals.163*164* <p>The characters listed here are used in non-localized patterns. Localized165* patterns use the corresponding characters taken from this formatter's166* {@code DecimalFormatSymbols} object instead, and these characters lose167* their special status. Two exceptions are the currency sign and quote, which168* are not localized.169*170* <blockquote>171* <table class="striped">172* <caption style="display:none">Chart showing symbol, location, localized, and meaning.</caption>173* <thead>174* <tr>175* <th scope="col" style="text-align:left">Symbol176* <th scope="col" style="text-align:left">Location177* <th scope="col" style="text-align:left">Localized?178* <th scope="col" style="text-align:left">Meaning179* </thead>180* <tbody>181* <tr style="vertical-align:top">182* <th scope="row">{@code 0}183* <td>Number184* <td>Yes185* <td>Digit186* <tr style="vertical-align: top">187* <th scope="row">{@code #}188* <td>Number189* <td>Yes190* <td>Digit, zero shows as absent191* <tr style="vertical-align:top">192* <th scope="row">{@code .}193* <td>Number194* <td>Yes195* <td>Decimal separator or monetary decimal separator196* <tr style="vertical-align: top">197* <th scope="row">{@code -}198* <td>Number199* <td>Yes200* <td>Minus sign201* <tr style="vertical-align:top">202* <th scope="row">{@code ,}203* <td>Number204* <td>Yes205* <td>Grouping separator or monetary grouping separator206* <tr style="vertical-align: top">207* <th scope="row">{@code E}208* <td>Number209* <td>Yes210* <td>Separates mantissa and exponent in scientific notation.211* <em>Need not be quoted in prefix or suffix.</em>212* <tr style="vertical-align:top">213* <th scope="row">{@code ;}214* <td>Subpattern boundary215* <td>Yes216* <td>Separates positive and negative subpatterns217* <tr style="vertical-align: top">218* <th scope="row">{@code %}219* <td>Prefix or suffix220* <td>Yes221* <td>Multiply by 100 and show as percentage222* <tr style="vertical-align:top">223* <th scope="row">{@code \u2030}224* <td>Prefix or suffix225* <td>Yes226* <td>Multiply by 1000 and show as per mille value227* <tr style="vertical-align: top">228* <th scope="row">{@code ¤} ({@code \u00A4})229* <td>Prefix or suffix230* <td>No231* <td>Currency sign, replaced by currency symbol. If232* doubled, replaced by international currency symbol.233* If present in a pattern, the monetary decimal/grouping separators234* are used instead of the decimal/grouping separators.235* <tr style="vertical-align:top">236* <th scope="row">{@code '}237* <td>Prefix or suffix238* <td>No239* <td>Used to quote special characters in a prefix or suffix,240* for example, {@code "'#'#"} formats 123 to241* {@code "#123"}. To create a single quote242* itself, use two in a row: {@code "# o''clock"}.243* </tbody>244* </table>245* </blockquote>246*247* <h3>Scientific Notation</h3>248*249* <p>Numbers in scientific notation are expressed as the product of a mantissa250* and a power of ten, for example, 1234 can be expressed as 1.234 x 10^3. The251* mantissa is often in the range 1.0 ≤ x {@literal <} 10.0, but it need not252* be.253* {@code DecimalFormat} can be instructed to format and parse scientific254* notation <em>only via a pattern</em>; there is currently no factory method255* that creates a scientific notation format. In a pattern, the exponent256* character immediately followed by one or more digit characters indicates257* scientific notation. Example: {@code "0.###E0"} formats the number258* 1234 as {@code "1.234E3"}.259*260* <ul>261* <li>The number of digit characters after the exponent character gives the262* minimum exponent digit count. There is no maximum. Negative exponents are263* formatted using the localized minus sign, <em>not</em> the prefix and suffix264* from the pattern. This allows patterns such as {@code "0.###E0 m/s"}.265*266* <li>The minimum and maximum number of integer digits are interpreted267* together:268*269* <ul>270* <li>If the maximum number of integer digits is greater than their minimum number271* and greater than 1, it forces the exponent to be a multiple of the maximum272* number of integer digits, and the minimum number of integer digits to be273* interpreted as 1. The most common use of this is to generate274* <em>engineering notation</em>, in which the exponent is a multiple of three,275* e.g., {@code "##0.#####E0"}. Using this pattern, the number 12345276* formats to {@code "12.345E3"}, and 123456 formats to277* {@code "123.456E3"}.278*279* <li>Otherwise, the minimum number of integer digits is achieved by adjusting the280* exponent. Example: 0.00123 formatted with {@code "00.###E0"} yields281* {@code "12.3E-4"}.282* </ul>283*284* <li>The number of significant digits in the mantissa is the sum of the285* <em>minimum integer</em> and <em>maximum fraction</em> digits, and is286* unaffected by the maximum integer digits. For example, 12345 formatted with287* {@code "##0.##E0"} is {@code "12.3E3"}. To show all digits, set288* the significant digits count to zero. The number of significant digits289* does not affect parsing.290*291* <li>Exponential patterns may not contain grouping separators.292* </ul>293*294* <h3>Rounding</h3>295*296* {@code DecimalFormat} provides rounding modes defined in297* {@link java.math.RoundingMode} for formatting. By default, it uses298* {@link java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}.299*300* <h3>Digits</h3>301*302* For formatting, {@code DecimalFormat} uses the ten consecutive303* characters starting with the localized zero digit defined in the304* {@code DecimalFormatSymbols} object as digits. For parsing, these305* digits as well as all Unicode decimal digits, as defined by306* {@link Character#digit Character.digit}, are recognized.307*308* <h4>Special Values</h4>309*310* <p>{@code NaN} is formatted as a string, which typically has a single character311* {@code \uFFFD}. This string is determined by the312* {@code DecimalFormatSymbols} object. This is the only value for which313* the prefixes and suffixes are not used.314*315* <p>Infinity is formatted as a string, which typically has a single character316* {@code \u221E}, with the positive or negative prefixes and suffixes317* applied. The infinity string is determined by the318* {@code DecimalFormatSymbols} object.319*320* <p>Negative zero ({@code "-0"}) parses to321* <ul>322* <li>{@code BigDecimal(0)} if {@code isParseBigDecimal()} is323* true,324* <li>{@code Long(0)} if {@code isParseBigDecimal()} is false325* and {@code isParseIntegerOnly()} is true,326* <li>{@code Double(-0.0)} if both {@code isParseBigDecimal()}327* and {@code isParseIntegerOnly()} are false.328* </ul>329*330* <h3><a id="synchronization">Synchronization</a></h3>331*332* <p>333* Decimal formats are generally not synchronized.334* It is recommended to create separate format instances for each thread.335* If multiple threads access a format concurrently, it must be synchronized336* externally.337*338* <h3>Example</h3>339*340* <blockquote><pre><strong>{@code341* // Print out a number using the localized number, integer, currency,342* // and percent format for each locale}</strong>{@code343* Locale[] locales = NumberFormat.getAvailableLocales();344* double myNumber = -1234.56;345* NumberFormat form;346* for (int j = 0; j < 4; ++j) {347* System.out.println("FORMAT");348* for (int i = 0; i < locales.length; ++i) {349* if (locales[i].getCountry().length() == 0) {350* continue; // Skip language-only locales351* }352* System.out.print(locales[i].getDisplayName());353* switch (j) {354* case 0:355* form = NumberFormat.getInstance(locales[i]); break;356* case 1:357* form = NumberFormat.getIntegerInstance(locales[i]); break;358* case 2:359* form = NumberFormat.getCurrencyInstance(locales[i]); break;360* default:361* form = NumberFormat.getPercentInstance(locales[i]); break;362* }363* if (form instanceof DecimalFormat) {364* System.out.print(": " + ((DecimalFormat) form).toPattern());365* }366* System.out.print(" -> " + form.format(myNumber));367* try {368* System.out.println(" -> " + form.parse(form.format(myNumber)));369* } catch (ParseException e) {}370* }371* }372* }</pre></blockquote>373*374* @see <a href="http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html">Java Tutorial</a>375* @see NumberFormat376* @see DecimalFormatSymbols377* @see ParsePosition378* @author Mark Davis379* @author Alan Liu380* @since 1.1381*/382public class DecimalFormat extends NumberFormat {383384/**385* Creates a DecimalFormat using the default pattern and symbols386* for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale.387* This is a convenient way to obtain a388* DecimalFormat when internationalization is not the main concern.389* <p>390* To obtain standard formats for a given locale, use the factory methods391* on NumberFormat such as getNumberInstance. These factories will392* return the most appropriate sub-class of NumberFormat for a given393* locale.394*395* @see java.text.NumberFormat#getInstance396* @see java.text.NumberFormat#getNumberInstance397* @see java.text.NumberFormat#getCurrencyInstance398* @see java.text.NumberFormat#getPercentInstance399*/400public DecimalFormat() {401// Get the pattern for the default locale.402Locale def = Locale.getDefault(Locale.Category.FORMAT);403LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(NumberFormatProvider.class, def);404if (!(adapter instanceof ResourceBundleBasedAdapter)) {405adapter = LocaleProviderAdapter.getResourceBundleBased();406}407String[] all = adapter.getLocaleResources(def).getNumberPatterns();408409// Always applyPattern after the symbols are set410this.symbols = DecimalFormatSymbols.getInstance(def);411applyPattern(all[0], false);412}413414415/**416* Creates a DecimalFormat using the given pattern and the symbols417* for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale.418* This is a convenient way to obtain a419* DecimalFormat when internationalization is not the main concern.420* <p>421* To obtain standard formats for a given locale, use the factory methods422* on NumberFormat such as getNumberInstance. These factories will423* return the most appropriate sub-class of NumberFormat for a given424* locale.425*426* @param pattern a non-localized pattern string.427* @throws NullPointerException if {@code pattern} is null428* @throws IllegalArgumentException if the given pattern is invalid.429* @see java.text.NumberFormat#getInstance430* @see java.text.NumberFormat#getNumberInstance431* @see java.text.NumberFormat#getCurrencyInstance432* @see java.text.NumberFormat#getPercentInstance433*/434public DecimalFormat(String pattern) {435// Always applyPattern after the symbols are set436this.symbols = DecimalFormatSymbols.getInstance(Locale.getDefault(Locale.Category.FORMAT));437applyPattern(pattern, false);438}439440441/**442* Creates a DecimalFormat using the given pattern and symbols.443* Use this constructor when you need to completely customize the444* behavior of the format.445* <p>446* To obtain standard formats for a given447* locale, use the factory methods on NumberFormat such as448* getInstance or getCurrencyInstance. If you need only minor adjustments449* to a standard format, you can modify the format returned by450* a NumberFormat factory method.451*452* @param pattern a non-localized pattern string453* @param symbols the set of symbols to be used454* @throws NullPointerException if any of the given arguments is null455* @throws IllegalArgumentException if the given pattern is invalid456* @see java.text.NumberFormat#getInstance457* @see java.text.NumberFormat#getNumberInstance458* @see java.text.NumberFormat#getCurrencyInstance459* @see java.text.NumberFormat#getPercentInstance460* @see java.text.DecimalFormatSymbols461*/462public DecimalFormat (String pattern, DecimalFormatSymbols symbols) {463// Always applyPattern after the symbols are set464this.symbols = (DecimalFormatSymbols)symbols.clone();465applyPattern(pattern, false);466}467468469// Overrides470/**471* Formats a number and appends the resulting text to the given string472* buffer.473* The number can be of any subclass of {@link java.lang.Number}.474* <p>475* This implementation uses the maximum precision permitted.476* @param number the number to format477* @param toAppendTo the {@code StringBuffer} to which the formatted478* text is to be appended479* @param pos keeps track on the position of the field within the480* returned string. For example, for formatting a number481* {@code 1234567.89} in {@code Locale.US} locale,482* if the given {@code fieldPosition} is483* {@link NumberFormat#INTEGER_FIELD}, the begin index484* and end index of {@code fieldPosition} will be set485* to 0 and 9, respectively for the output string486* {@code 1,234,567.89}.487* @return the value passed in as {@code toAppendTo}488* @throws IllegalArgumentException if {@code number} is489* null or not an instance of {@code Number}.490* @throws NullPointerException if {@code toAppendTo} or491* {@code pos} is null492* @throws ArithmeticException if rounding is needed with rounding493* mode being set to RoundingMode.UNNECESSARY494* @see java.text.FieldPosition495*/496@Override497public final StringBuffer format(Object number,498StringBuffer toAppendTo,499FieldPosition pos) {500if (number instanceof Long || number instanceof Integer ||501number instanceof Short || number instanceof Byte ||502number instanceof AtomicInteger ||503number instanceof AtomicLong ||504(number instanceof BigInteger &&505((BigInteger)number).bitLength () < 64)) {506return format(((Number)number).longValue(), toAppendTo, pos);507} else if (number instanceof BigDecimal) {508return format((BigDecimal)number, toAppendTo, pos);509} else if (number instanceof BigInteger) {510return format((BigInteger)number, toAppendTo, pos);511} else if (number instanceof Number) {512return format(((Number)number).doubleValue(), toAppendTo, pos);513} else {514throw new IllegalArgumentException("Cannot format given Object as a Number");515}516}517518/**519* Formats a double to produce a string.520* @param number The double to format521* @param result where the text is to be appended522* @param fieldPosition keeps track on the position of the field within523* the returned string. For example, for formatting524* a number {@code 1234567.89} in {@code Locale.US}525* locale, if the given {@code fieldPosition} is526* {@link NumberFormat#INTEGER_FIELD}, the begin index527* and end index of {@code fieldPosition} will be set528* to 0 and 9, respectively for the output string529* {@code 1,234,567.89}.530* @throws NullPointerException if {@code result} or531* {@code fieldPosition} is {@code null}532* @throws ArithmeticException if rounding is needed with rounding533* mode being set to RoundingMode.UNNECESSARY534* @return The formatted number string535* @see java.text.FieldPosition536*/537@Override538public StringBuffer format(double number, StringBuffer result,539FieldPosition fieldPosition) {540// If fieldPosition is a DontCareFieldPosition instance we can541// try to go to fast-path code.542boolean tryFastPath = false;543if (fieldPosition == DontCareFieldPosition.INSTANCE)544tryFastPath = true;545else {546fieldPosition.setBeginIndex(0);547fieldPosition.setEndIndex(0);548}549550if (tryFastPath) {551String tempResult = fastFormat(number);552if (tempResult != null) {553result.append(tempResult);554return result;555}556}557558// if fast-path could not work, we fallback to standard code.559return format(number, result, fieldPosition.getFieldDelegate());560}561562/**563* Formats a double to produce a string.564* @param number The double to format565* @param result where the text is to be appended566* @param delegate notified of locations of sub fields567* @throws ArithmeticException if rounding is needed with rounding568* mode being set to RoundingMode.UNNECESSARY569* @return The formatted number string570*/571StringBuffer format(double number, StringBuffer result,572FieldDelegate delegate) {573574boolean nanOrInfinity = handleNaN(number, result, delegate);575if (nanOrInfinity) {576return result;577}578579/* Detecting whether a double is negative is easy with the exception of580* the value -0.0. This is a double which has a zero mantissa (and581* exponent), but a negative sign bit. It is semantically distinct from582* a zero with a positive sign bit, and this distinction is important583* to certain kinds of computations. However, it's a little tricky to584* detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you may585* ask, does it behave distinctly from +0.0? Well, 1/(-0.0) ==586* -Infinity. Proper detection of -0.0 is needed to deal with the587* issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98.588*/589boolean isNegative = ((number < 0.0) || (number == 0.0 && 1/number < 0.0)) ^ (multiplier < 0);590591if (multiplier != 1) {592number *= multiplier;593}594595nanOrInfinity = handleInfinity(number, result, delegate, isNegative);596if (nanOrInfinity) {597return result;598}599600if (isNegative) {601number = -number;602}603604// at this point we are guaranteed a nonnegative finite number.605assert (number >= 0 && !Double.isInfinite(number));606return doubleSubformat(number, result, delegate, isNegative);607}608609/**610* Checks if the given {@code number} is {@code Double.NaN}. if yes;611* appends the NaN symbol to the result string. The NaN string is612* determined by the DecimalFormatSymbols object.613* @param number the double number to format614* @param result where the text is to be appended615* @param delegate notified of locations of sub fields616* @return true, if number is a NaN; false otherwise617*/618boolean handleNaN(double number, StringBuffer result,619FieldDelegate delegate) {620if (Double.isNaN(number)621|| (Double.isInfinite(number) && multiplier == 0)) {622int iFieldStart = result.length();623result.append(symbols.getNaN());624delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,625iFieldStart, result.length(), result);626return true;627}628return false;629}630631/**632* Checks if the given {@code number} is {@code Double.NEGATIVE_INFINITY}633* or {@code Double.POSITIVE_INFINITY}. if yes;634* appends the infinity string to the result string. The infinity string is635* determined by the DecimalFormatSymbols object.636* @param number the double number to format637* @param result where the text is to be appended638* @param delegate notified of locations of sub fields639* @param isNegative whether the given {@code number} is negative640* @return true, if number is a {@code Double.NEGATIVE_INFINITY} or641* {@code Double.POSITIVE_INFINITY}; false otherwise642*/643boolean handleInfinity(double number, StringBuffer result,644FieldDelegate delegate, boolean isNegative) {645if (Double.isInfinite(number)) {646if (isNegative) {647append(result, negativePrefix, delegate,648getNegativePrefixFieldPositions(), Field.SIGN);649} else {650append(result, positivePrefix, delegate,651getPositivePrefixFieldPositions(), Field.SIGN);652}653654int iFieldStart = result.length();655result.append(symbols.getInfinity());656delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,657iFieldStart, result.length(), result);658659if (isNegative) {660append(result, negativeSuffix, delegate,661getNegativeSuffixFieldPositions(), Field.SIGN);662} else {663append(result, positiveSuffix, delegate,664getPositiveSuffixFieldPositions(), Field.SIGN);665}666667return true;668}669return false;670}671672StringBuffer doubleSubformat(double number, StringBuffer result,673FieldDelegate delegate, boolean isNegative) {674synchronized (digitList) {675int maxIntDigits = super.getMaximumIntegerDigits();676int minIntDigits = super.getMinimumIntegerDigits();677int maxFraDigits = super.getMaximumFractionDigits();678int minFraDigits = super.getMinimumFractionDigits();679680digitList.set(isNegative, number, useExponentialNotation681? maxIntDigits + maxFraDigits : maxFraDigits,682!useExponentialNotation);683return subformat(result, delegate, isNegative, false,684maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);685}686}687688/**689* Format a long to produce a string.690* @param number The long to format691* @param result where the text is to be appended692* @param fieldPosition keeps track on the position of the field within693* the returned string. For example, for formatting694* a number {@code 123456789} in {@code Locale.US}695* locale, if the given {@code fieldPosition} is696* {@link NumberFormat#INTEGER_FIELD}, the begin index697* and end index of {@code fieldPosition} will be set698* to 0 and 11, respectively for the output string699* {@code 123,456,789}.700* @throws NullPointerException if {@code result} or701* {@code fieldPosition} is {@code null}702* @throws ArithmeticException if rounding is needed with rounding703* mode being set to RoundingMode.UNNECESSARY704* @return The formatted number string705* @see java.text.FieldPosition706*/707@Override708public StringBuffer format(long number, StringBuffer result,709FieldPosition fieldPosition) {710fieldPosition.setBeginIndex(0);711fieldPosition.setEndIndex(0);712713return format(number, result, fieldPosition.getFieldDelegate());714}715716/**717* Format a long to produce a string.718* @param number The long to format719* @param result where the text is to be appended720* @param delegate notified of locations of sub fields721* @return The formatted number string722* @throws ArithmeticException if rounding is needed with rounding723* mode being set to RoundingMode.UNNECESSARY724* @see java.text.FieldPosition725*/726StringBuffer format(long number, StringBuffer result,727FieldDelegate delegate) {728boolean isNegative = (number < 0);729if (isNegative) {730number = -number;731}732733// In general, long values always represent real finite numbers, so734// we don't have to check for +/- Infinity or NaN. However, there735// is one case we have to be careful of: The multiplier can push736// a number near MIN_VALUE or MAX_VALUE outside the legal range. We737// check for this before multiplying, and if it happens we use738// BigInteger instead.739boolean useBigInteger = false;740if (number < 0) { // This can only happen if number == Long.MIN_VALUE.741if (multiplier != 0) {742useBigInteger = true;743}744} else if (multiplier != 1 && multiplier != 0) {745long cutoff = Long.MAX_VALUE / multiplier;746if (cutoff < 0) {747cutoff = -cutoff;748}749useBigInteger = (number > cutoff);750}751752if (useBigInteger) {753if (isNegative) {754number = -number;755}756BigInteger bigIntegerValue = BigInteger.valueOf(number);757return format(bigIntegerValue, result, delegate, true);758}759760number *= multiplier;761if (number == 0) {762isNegative = false;763} else {764if (multiplier < 0) {765number = -number;766isNegative = !isNegative;767}768}769770synchronized(digitList) {771int maxIntDigits = super.getMaximumIntegerDigits();772int minIntDigits = super.getMinimumIntegerDigits();773int maxFraDigits = super.getMaximumFractionDigits();774int minFraDigits = super.getMinimumFractionDigits();775776digitList.set(isNegative, number,777useExponentialNotation ? maxIntDigits + maxFraDigits : 0);778779return subformat(result, delegate, isNegative, true,780maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);781}782}783784/**785* Formats a BigDecimal to produce a string.786* @param number The BigDecimal to format787* @param result where the text is to be appended788* @param fieldPosition keeps track on the position of the field within789* the returned string. For example, for formatting790* a number {@code 1234567.89} in {@code Locale.US}791* locale, if the given {@code fieldPosition} is792* {@link NumberFormat#INTEGER_FIELD}, the begin index793* and end index of {@code fieldPosition} will be set794* to 0 and 9, respectively for the output string795* {@code 1,234,567.89}.796* @return The formatted number string797* @throws ArithmeticException if rounding is needed with rounding798* mode being set to RoundingMode.UNNECESSARY799* @see java.text.FieldPosition800*/801private StringBuffer format(BigDecimal number, StringBuffer result,802FieldPosition fieldPosition) {803fieldPosition.setBeginIndex(0);804fieldPosition.setEndIndex(0);805return format(number, result, fieldPosition.getFieldDelegate());806}807808/**809* Formats a BigDecimal to produce a string.810* @param number The BigDecimal to format811* @param result where the text is to be appended812* @param delegate notified of locations of sub fields813* @throws ArithmeticException if rounding is needed with rounding814* mode being set to RoundingMode.UNNECESSARY815* @return The formatted number string816*/817StringBuffer format(BigDecimal number, StringBuffer result,818FieldDelegate delegate) {819if (multiplier != 1) {820number = number.multiply(getBigDecimalMultiplier());821}822boolean isNegative = number.signum() == -1;823if (isNegative) {824number = number.negate();825}826827synchronized(digitList) {828int maxIntDigits = getMaximumIntegerDigits();829int minIntDigits = getMinimumIntegerDigits();830int maxFraDigits = getMaximumFractionDigits();831int minFraDigits = getMinimumFractionDigits();832int maximumDigits = maxIntDigits + maxFraDigits;833834digitList.set(isNegative, number, useExponentialNotation ?835((maximumDigits < 0) ? Integer.MAX_VALUE : maximumDigits) :836maxFraDigits, !useExponentialNotation);837838return subformat(result, delegate, isNegative, false,839maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);840}841}842843/**844* Format a BigInteger to produce a string.845* @param number The BigInteger to format846* @param result where the text is to be appended847* @param fieldPosition keeps track on the position of the field within848* the returned string. For example, for formatting849* a number {@code 123456789} in {@code Locale.US}850* locale, if the given {@code fieldPosition} is851* {@link NumberFormat#INTEGER_FIELD}, the begin index852* and end index of {@code fieldPosition} will be set853* to 0 and 11, respectively for the output string854* {@code 123,456,789}.855* @return The formatted number string856* @throws ArithmeticException if rounding is needed with rounding857* mode being set to RoundingMode.UNNECESSARY858* @see java.text.FieldPosition859*/860private StringBuffer format(BigInteger number, StringBuffer result,861FieldPosition fieldPosition) {862fieldPosition.setBeginIndex(0);863fieldPosition.setEndIndex(0);864865return format(number, result, fieldPosition.getFieldDelegate(), false);866}867868/**869* Format a BigInteger to produce a string.870* @param number The BigInteger to format871* @param result where the text is to be appended872* @param delegate notified of locations of sub fields873* @return The formatted number string874* @throws ArithmeticException if rounding is needed with rounding875* mode being set to RoundingMode.UNNECESSARY876* @see java.text.FieldPosition877*/878StringBuffer format(BigInteger number, StringBuffer result,879FieldDelegate delegate, boolean formatLong) {880if (multiplier != 1) {881number = number.multiply(getBigIntegerMultiplier());882}883boolean isNegative = number.signum() == -1;884if (isNegative) {885number = number.negate();886}887888synchronized(digitList) {889int maxIntDigits, minIntDigits, maxFraDigits, minFraDigits, maximumDigits;890if (formatLong) {891maxIntDigits = super.getMaximumIntegerDigits();892minIntDigits = super.getMinimumIntegerDigits();893maxFraDigits = super.getMaximumFractionDigits();894minFraDigits = super.getMinimumFractionDigits();895maximumDigits = maxIntDigits + maxFraDigits;896} else {897maxIntDigits = getMaximumIntegerDigits();898minIntDigits = getMinimumIntegerDigits();899maxFraDigits = getMaximumFractionDigits();900minFraDigits = getMinimumFractionDigits();901maximumDigits = maxIntDigits + maxFraDigits;902if (maximumDigits < 0) {903maximumDigits = Integer.MAX_VALUE;904}905}906907digitList.set(isNegative, number,908useExponentialNotation ? maximumDigits : 0);909910return subformat(result, delegate, isNegative, true,911maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);912}913}914915/**916* Formats an Object producing an {@code AttributedCharacterIterator}.917* You can use the returned {@code AttributedCharacterIterator}918* to build the resulting String, as well as to determine information919* about the resulting String.920* <p>921* Each attribute key of the AttributedCharacterIterator will be of type922* {@code NumberFormat.Field}, with the attribute value being the923* same as the attribute key.924*925* @throws NullPointerException if obj is null.926* @throws IllegalArgumentException when the Format cannot format the927* given object.928* @throws ArithmeticException if rounding is needed with rounding929* mode being set to RoundingMode.UNNECESSARY930* @param obj The object to format931* @return AttributedCharacterIterator describing the formatted value.932* @since 1.4933*/934@Override935public AttributedCharacterIterator formatToCharacterIterator(Object obj) {936CharacterIteratorFieldDelegate delegate =937new CharacterIteratorFieldDelegate();938StringBuffer sb = new StringBuffer();939940if (obj instanceof Double || obj instanceof Float) {941format(((Number)obj).doubleValue(), sb, delegate);942} else if (obj instanceof Long || obj instanceof Integer ||943obj instanceof Short || obj instanceof Byte ||944obj instanceof AtomicInteger || obj instanceof AtomicLong) {945format(((Number)obj).longValue(), sb, delegate);946} else if (obj instanceof BigDecimal) {947format((BigDecimal)obj, sb, delegate);948} else if (obj instanceof BigInteger) {949format((BigInteger)obj, sb, delegate, false);950} else if (obj == null) {951throw new NullPointerException(952"formatToCharacterIterator must be passed non-null object");953} else {954throw new IllegalArgumentException(955"Cannot format given Object as a Number");956}957return delegate.getIterator(sb.toString());958}959960// ==== Begin fast-path formatting logic for double =========================961962/* Fast-path formatting will be used for format(double ...) methods iff a963* number of conditions are met (see checkAndSetFastPathStatus()):964* - Only if instance properties meet the right predefined conditions.965* - The abs value of the double to format is <= Integer.MAX_VALUE.966*967* The basic approach is to split the binary to decimal conversion of a968* double value into two phases:969* * The conversion of the integer portion of the double.970* * The conversion of the fractional portion of the double971* (limited to two or three digits).972*973* The isolation and conversion of the integer portion of the double is974* straightforward. The conversion of the fraction is more subtle and relies975* on some rounding properties of double to the decimal precisions in976* question. Using the terminology of BigDecimal, this fast-path algorithm977* is applied when a double value has a magnitude less than Integer.MAX_VALUE978* and rounding is to nearest even and the destination format has two or979* three digits of *scale* (digits after the decimal point).980*981* Under a rounding to nearest even policy, the returned result is a digit982* string of a number in the (in this case decimal) destination format983* closest to the exact numerical value of the (in this case binary) input984* value. If two destination format numbers are equally distant, the one985* with the last digit even is returned. To compute such a correctly rounded986* value, some information about digits beyond the smallest returned digit987* position needs to be consulted.988*989* In general, a guard digit, a round digit, and a sticky *bit* are needed990* beyond the returned digit position. If the discarded portion of the input991* is sufficiently large, the returned digit string is incremented. In round992* to nearest even, this threshold to increment occurs near the half-way993* point between digits. The sticky bit records if there are any remaining994* trailing digits of the exact input value in the new format; the sticky bit995* is consulted only in close to half-way rounding cases.996*997* Given the computation of the digit and bit values, rounding is then998* reduced to a table lookup problem. For decimal, the even/odd cases look999* like this:1000*1001* Last Round Sticky1002* 6 5 0 => 6 // exactly halfway, return even digit.1003* 6 5 1 => 7 // a little bit more than halfway, round up.1004* 7 5 0 => 8 // exactly halfway, round up to even.1005* 7 5 1 => 8 // a little bit more than halfway, round up.1006* With analogous entries for other even and odd last-returned digits.1007*1008* However, decimal negative powers of 5 smaller than 0.5 are *not* exactly1009* representable as binary fraction. In particular, 0.005 (the round limit1010* for a two-digit scale) and 0.0005 (the round limit for a three-digit1011* scale) are not representable. Therefore, for input values near these cases1012* the sticky bit is known to be set which reduces the rounding logic to:1013*1014* Last Round Sticky1015* 6 5 1 => 7 // a little bit more than halfway, round up.1016* 7 5 1 => 8 // a little bit more than halfway, round up.1017*1018* In other words, if the round digit is 5, the sticky bit is known to be1019* set. If the round digit is something other than 5, the sticky bit is not1020* relevant. Therefore, some of the logic about whether or not to increment1021* the destination *decimal* value can occur based on tests of *binary*1022* computations of the binary input number.1023*/10241025/**1026* Check validity of using fast-path for this instance. If fast-path is valid1027* for this instance, sets fast-path state as true and initializes fast-path1028* utility fields as needed.1029*1030* This method is supposed to be called rarely, otherwise that will break the1031* fast-path performance. That means avoiding frequent changes of the1032* properties of the instance, since for most properties, each time a change1033* happens, a call to this method is needed at the next format call.1034*1035* FAST-PATH RULES:1036* Similar to the default DecimalFormat instantiation case.1037* More precisely:1038* - HALF_EVEN rounding mode,1039* - isGroupingUsed() is true,1040* - groupingSize of 3,1041* - multiplier is 1,1042* - Decimal separator not mandatory,1043* - No use of exponential notation,1044* - minimumIntegerDigits is exactly 1 and maximumIntegerDigits at least 101045* - For number of fractional digits, the exact values found in the default case:1046* Currency : min = max = 2.1047* Decimal : min = 0. max = 3.1048*1049*/1050private boolean checkAndSetFastPathStatus() {10511052boolean fastPathWasOn = isFastPath;10531054if ((roundingMode == RoundingMode.HALF_EVEN) &&1055(isGroupingUsed()) &&1056(groupingSize == 3) &&1057(multiplier == 1) &&1058(!decimalSeparatorAlwaysShown) &&1059(!useExponentialNotation)) {10601061// The fast-path algorithm is semi-hardcoded against1062// minimumIntegerDigits and maximumIntegerDigits.1063isFastPath = ((minimumIntegerDigits == 1) &&1064(maximumIntegerDigits >= 10));10651066// The fast-path algorithm is hardcoded against1067// minimumFractionDigits and maximumFractionDigits.1068if (isFastPath) {1069if (isCurrencyFormat) {1070if ((minimumFractionDigits != 2) ||1071(maximumFractionDigits != 2))1072isFastPath = false;1073} else if ((minimumFractionDigits != 0) ||1074(maximumFractionDigits != 3))1075isFastPath = false;1076}1077} else1078isFastPath = false;10791080resetFastPathData(fastPathWasOn);1081fastPathCheckNeeded = false;10821083/*1084* Returns true after successfully checking the fast path condition and1085* setting the fast path data. The return value is used by the1086* fastFormat() method to decide whether to call the resetFastPathData1087* method to reinitialize fast path data or is it already initialized1088* in this method.1089*/1090return true;1091}10921093private void resetFastPathData(boolean fastPathWasOn) {1094// Since some instance properties may have changed while still falling1095// in the fast-path case, we need to reinitialize fastPathData anyway.1096if (isFastPath) {1097// We need to instantiate fastPathData if not already done.1098if (fastPathData == null) {1099fastPathData = new FastPathData();1100}11011102// Sets up the locale specific constants used when formatting.1103// '0' is our default representation of zero.1104fastPathData.zeroDelta = symbols.getZeroDigit() - '0';1105fastPathData.groupingChar = isCurrencyFormat ?1106symbols.getMonetaryGroupingSeparator() :1107symbols.getGroupingSeparator();11081109// Sets up fractional constants related to currency/decimal pattern.1110fastPathData.fractionalMaxIntBound = (isCurrencyFormat)1111? 99 : 999;1112fastPathData.fractionalScaleFactor = (isCurrencyFormat)1113? 100.0d : 1000.0d;11141115// Records the need for adding prefix or suffix1116fastPathData.positiveAffixesRequired1117= !positivePrefix.isEmpty() || !positiveSuffix.isEmpty();1118fastPathData.negativeAffixesRequired1119= !negativePrefix.isEmpty() || !negativeSuffix.isEmpty();11201121// Creates a cached char container for result, with max possible size.1122int maxNbIntegralDigits = 10;1123int maxNbGroups = 3;1124int containerSize1125= Math.max(positivePrefix.length(), negativePrefix.length())1126+ maxNbIntegralDigits + maxNbGroups + 11127+ maximumFractionDigits1128+ Math.max(positiveSuffix.length(), negativeSuffix.length());11291130fastPathData.fastPathContainer = new char[containerSize];11311132// Sets up prefix and suffix char arrays constants.1133fastPathData.charsPositiveSuffix = positiveSuffix.toCharArray();1134fastPathData.charsNegativeSuffix = negativeSuffix.toCharArray();1135fastPathData.charsPositivePrefix = positivePrefix.toCharArray();1136fastPathData.charsNegativePrefix = negativePrefix.toCharArray();11371138// Sets up fixed index positions for integral and fractional digits.1139// Sets up decimal point in cached result container.1140int longestPrefixLength1141= Math.max(positivePrefix.length(),1142negativePrefix.length());1143int decimalPointIndex1144= maxNbIntegralDigits + maxNbGroups + longestPrefixLength;11451146fastPathData.integralLastIndex = decimalPointIndex - 1;1147fastPathData.fractionalFirstIndex = decimalPointIndex + 1;1148fastPathData.fastPathContainer[decimalPointIndex]1149= isCurrencyFormat1150? symbols.getMonetaryDecimalSeparator()1151: symbols.getDecimalSeparator();11521153} else if (fastPathWasOn) {1154// Previous state was fast-path and is no more.1155// Resets cached array constants.1156fastPathData.fastPathContainer = null;1157fastPathData.charsPositiveSuffix = null;1158fastPathData.charsNegativeSuffix = null;1159fastPathData.charsPositivePrefix = null;1160fastPathData.charsNegativePrefix = null;1161}1162}11631164/**1165* Returns true if rounding-up must be done on {@code scaledFractionalPartAsInt},1166* false otherwise.1167*1168* This is a utility method that takes correct half-even rounding decision on1169* passed fractional value at the scaled decimal point (2 digits for currency1170* case and 3 for decimal case), when the approximated fractional part after1171* scaled decimal point is exactly 0.5d. This is done by means of exact1172* calculations on the {@code fractionalPart} floating-point value.1173*1174* This method is supposed to be called by private {@code fastDoubleFormat}1175* method only.1176*1177* The algorithms used for the exact calculations are :1178*1179* The <b><i>FastTwoSum</i></b> algorithm, from T.J.Dekker, described in the1180* papers "<i>A Floating-Point Technique for Extending the Available1181* Precision</i>" by Dekker, and in "<i>Adaptive Precision Floating-Point1182* Arithmetic and Fast Robust Geometric Predicates</i>" from J.Shewchuk.1183*1184* A modified version of <b><i>Sum2S</i></b> cascaded summation described in1185* "<i>Accurate Sum and Dot Product</i>" from Takeshi Ogita and All. As1186* Ogita says in this paper this is an equivalent of the Kahan-Babuska's1187* summation algorithm because we order the terms by magnitude before summing1188* them. For this reason we can use the <i>FastTwoSum</i> algorithm rather1189* than the more expensive Knuth's <i>TwoSum</i>.1190*1191* We do this to avoid a more expensive exact "<i>TwoProduct</i>" algorithm,1192* like those described in Shewchuk's paper above. See comments in the code1193* below.1194*1195* @param fractionalPart The fractional value on which we take rounding1196* decision.1197* @param scaledFractionalPartAsInt The integral part of the scaled1198* fractional value.1199*1200* @return the decision that must be taken regarding half-even rounding.1201*/1202private boolean exactRoundUp(double fractionalPart,1203int scaledFractionalPartAsInt) {12041205/* exactRoundUp() method is called by fastDoubleFormat() only.1206* The precondition expected to be verified by the passed parameters is :1207* scaledFractionalPartAsInt ==1208* (int) (fractionalPart * fastPathData.fractionalScaleFactor).1209* This is ensured by fastDoubleFormat() code.1210*/12111212/* We first calculate roundoff error made by fastDoubleFormat() on1213* the scaled fractional part. We do this with exact calculation on the1214* passed fractionalPart. Rounding decision will then be taken from roundoff.1215*/12161217/* ---- TwoProduct(fractionalPart, scale factor (i.e. 1000.0d or 100.0d)).1218*1219* The below is an optimized exact "TwoProduct" calculation of passed1220* fractional part with scale factor, using Ogita's Sum2S cascaded1221* summation adapted as Kahan-Babuska equivalent by using FastTwoSum1222* (much faster) rather than Knuth's TwoSum.1223*1224* We can do this because we order the summation from smallest to1225* greatest, so that FastTwoSum can be used without any additional error.1226*1227* The "TwoProduct" exact calculation needs 17 flops. We replace this by1228* a cascaded summation of FastTwoSum calculations, each involving an1229* exact multiply by a power of 2.1230*1231* Doing so saves overall 4 multiplications and 1 addition compared to1232* using traditional "TwoProduct".1233*1234* The scale factor is either 100 (currency case) or 1000 (decimal case).1235* - when 1000, we replace it by (1024 - 16 - 8) = 1000.1236* - when 100, we replace it by (128 - 32 + 4) = 100.1237* Every multiplication by a power of 2 (1024, 128, 32, 16, 8, 4) is exact.1238*1239*/1240double approxMax; // Will always be positive.1241double approxMedium; // Will always be negative.1242double approxMin;12431244double fastTwoSumApproximation = 0.0d;1245double fastTwoSumRoundOff = 0.0d;1246double bVirtual = 0.0d;12471248if (isCurrencyFormat) {1249// Scale is 100 = 128 - 32 + 4.1250// Multiply by 2**n is a shift. No roundoff. No error.1251approxMax = fractionalPart * 128.00d;1252approxMedium = - (fractionalPart * 32.00d);1253approxMin = fractionalPart * 4.00d;1254} else {1255// Scale is 1000 = 1024 - 16 - 8.1256// Multiply by 2**n is a shift. No roundoff. No error.1257approxMax = fractionalPart * 1024.00d;1258approxMedium = - (fractionalPart * 16.00d);1259approxMin = - (fractionalPart * 8.00d);1260}12611262// Shewchuk/Dekker's FastTwoSum(approxMedium, approxMin).1263assert(-approxMedium >= Math.abs(approxMin));1264fastTwoSumApproximation = approxMedium + approxMin;1265bVirtual = fastTwoSumApproximation - approxMedium;1266fastTwoSumRoundOff = approxMin - bVirtual;1267double approxS1 = fastTwoSumApproximation;1268double roundoffS1 = fastTwoSumRoundOff;12691270// Shewchuk/Dekker's FastTwoSum(approxMax, approxS1);1271assert(approxMax >= Math.abs(approxS1));1272fastTwoSumApproximation = approxMax + approxS1;1273bVirtual = fastTwoSumApproximation - approxMax;1274fastTwoSumRoundOff = approxS1 - bVirtual;1275double roundoff1000 = fastTwoSumRoundOff;1276double approx1000 = fastTwoSumApproximation;1277double roundoffTotal = roundoffS1 + roundoff1000;12781279// Shewchuk/Dekker's FastTwoSum(approx1000, roundoffTotal);1280assert(approx1000 >= Math.abs(roundoffTotal));1281fastTwoSumApproximation = approx1000 + roundoffTotal;1282bVirtual = fastTwoSumApproximation - approx1000;12831284// Now we have got the roundoff for the scaled fractional1285double scaledFractionalRoundoff = roundoffTotal - bVirtual;12861287// ---- TwoProduct(fractionalPart, scale (i.e. 1000.0d or 100.0d)) end.12881289/* ---- Taking the rounding decision1290*1291* We take rounding decision based on roundoff and half-even rounding1292* rule.1293*1294* The above TwoProduct gives us the exact roundoff on the approximated1295* scaled fractional, and we know that this approximation is exactly1296* 0.5d, since that has already been tested by the caller1297* (fastDoubleFormat).1298*1299* Decision comes first from the sign of the calculated exact roundoff.1300* - Since being exact roundoff, it cannot be positive with a scaled1301* fractional less than 0.5d, as well as negative with a scaled1302* fractional greater than 0.5d. That leaves us with following 3 cases.1303* - positive, thus scaled fractional == 0.500....0fff ==> round-up.1304* - negative, thus scaled fractional == 0.499....9fff ==> don't round-up.1305* - is zero, thus scaled fractioanl == 0.5 ==> half-even rounding applies :1306* we round-up only if the integral part of the scaled fractional is odd.1307*1308*/1309if (scaledFractionalRoundoff > 0.0) {1310return true;1311} else if (scaledFractionalRoundoff < 0.0) {1312return false;1313} else if ((scaledFractionalPartAsInt & 1) != 0) {1314return true;1315}13161317return false;13181319// ---- Taking the rounding decision end1320}13211322/**1323* Collects integral digits from passed {@code number}, while setting1324* grouping chars as needed. Updates {@code firstUsedIndex} accordingly.1325*1326* Loops downward starting from {@code backwardIndex} position (inclusive).1327*1328* @param number The int value from which we collect digits.1329* @param digitsBuffer The char array container where digits and grouping chars1330* are stored.1331* @param backwardIndex the position from which we start storing digits in1332* digitsBuffer.1333*1334*/1335private void collectIntegralDigits(int number,1336char[] digitsBuffer,1337int backwardIndex) {1338int index = backwardIndex;1339int q;1340int r;1341while (number > 999) {1342// Generates 3 digits per iteration.1343q = number / 1000;1344r = number - (q << 10) + (q << 4) + (q << 3); // -1024 +16 +8 = 1000.1345number = q;13461347digitsBuffer[index--] = DigitArrays.DigitOnes1000[r];1348digitsBuffer[index--] = DigitArrays.DigitTens1000[r];1349digitsBuffer[index--] = DigitArrays.DigitHundreds1000[r];1350digitsBuffer[index--] = fastPathData.groupingChar;1351}13521353// Collects last 3 or less digits.1354digitsBuffer[index] = DigitArrays.DigitOnes1000[number];1355if (number > 9) {1356digitsBuffer[--index] = DigitArrays.DigitTens1000[number];1357if (number > 99)1358digitsBuffer[--index] = DigitArrays.DigitHundreds1000[number];1359}13601361fastPathData.firstUsedIndex = index;1362}13631364/**1365* Collects the 2 (currency) or 3 (decimal) fractional digits from passed1366* {@code number}, starting at {@code startIndex} position1367* inclusive. There is no punctuation to set here (no grouping chars).1368* Updates {@code fastPathData.lastFreeIndex} accordingly.1369*1370*1371* @param number The int value from which we collect digits.1372* @param digitsBuffer The char array container where digits are stored.1373* @param startIndex the position from which we start storing digits in1374* digitsBuffer.1375*1376*/1377private void collectFractionalDigits(int number,1378char[] digitsBuffer,1379int startIndex) {1380int index = startIndex;13811382char digitOnes = DigitArrays.DigitOnes1000[number];1383char digitTens = DigitArrays.DigitTens1000[number];13841385if (isCurrencyFormat) {1386// Currency case. Always collects fractional digits.1387digitsBuffer[index++] = digitTens;1388digitsBuffer[index++] = digitOnes;1389} else if (number != 0) {1390// Decimal case. Hundreds will always be collected1391digitsBuffer[index++] = DigitArrays.DigitHundreds1000[number];13921393// Ending zeros won't be collected.1394if (digitOnes != '0') {1395digitsBuffer[index++] = digitTens;1396digitsBuffer[index++] = digitOnes;1397} else if (digitTens != '0')1398digitsBuffer[index++] = digitTens;13991400} else1401// This is decimal pattern and fractional part is zero.1402// We must remove decimal point from result.1403index--;14041405fastPathData.lastFreeIndex = index;1406}14071408/**1409* Internal utility.1410* Adds the passed {@code prefix} and {@code suffix} to {@code container}.1411*1412* @param container Char array container which to prepend/append the1413* prefix/suffix.1414* @param prefix Char sequence to prepend as a prefix.1415* @param suffix Char sequence to append as a suffix.1416*1417*/1418// private void addAffixes(boolean isNegative, char[] container) {1419private void addAffixes(char[] container, char[] prefix, char[] suffix) {14201421// We add affixes only if needed (affix length > 0).1422int pl = prefix.length;1423int sl = suffix.length;1424if (pl != 0) prependPrefix(prefix, pl, container);1425if (sl != 0) appendSuffix(suffix, sl, container);14261427}14281429/**1430* Prepends the passed {@code prefix} chars to given result1431* {@code container}. Updates {@code fastPathData.firstUsedIndex}1432* accordingly.1433*1434* @param prefix The prefix characters to prepend to result.1435* @param len The number of chars to prepend.1436* @param container Char array container which to prepend the prefix1437*/1438private void prependPrefix(char[] prefix,1439int len,1440char[] container) {14411442fastPathData.firstUsedIndex -= len;1443int startIndex = fastPathData.firstUsedIndex;14441445// If prefix to prepend is only 1 char long, just assigns this char.1446// If prefix is less or equal 4, we use a dedicated algorithm that1447// has shown to run faster than System.arraycopy.1448// If more than 4, we use System.arraycopy.1449if (len == 1)1450container[startIndex] = prefix[0];1451else if (len <= 4) {1452int dstLower = startIndex;1453int dstUpper = dstLower + len - 1;1454int srcUpper = len - 1;1455container[dstLower] = prefix[0];1456container[dstUpper] = prefix[srcUpper];14571458if (len > 2)1459container[++dstLower] = prefix[1];1460if (len == 4)1461container[--dstUpper] = prefix[2];1462} else1463System.arraycopy(prefix, 0, container, startIndex, len);1464}14651466/**1467* Appends the passed {@code suffix} chars to given result1468* {@code container}. Updates {@code fastPathData.lastFreeIndex}1469* accordingly.1470*1471* @param suffix The suffix characters to append to result.1472* @param len The number of chars to append.1473* @param container Char array container which to append the suffix1474*/1475private void appendSuffix(char[] suffix,1476int len,1477char[] container) {14781479int startIndex = fastPathData.lastFreeIndex;14801481// If suffix to append is only 1 char long, just assigns this char.1482// If suffix is less or equal 4, we use a dedicated algorithm that1483// has shown to run faster than System.arraycopy.1484// If more than 4, we use System.arraycopy.1485if (len == 1)1486container[startIndex] = suffix[0];1487else if (len <= 4) {1488int dstLower = startIndex;1489int dstUpper = dstLower + len - 1;1490int srcUpper = len - 1;1491container[dstLower] = suffix[0];1492container[dstUpper] = suffix[srcUpper];14931494if (len > 2)1495container[++dstLower] = suffix[1];1496if (len == 4)1497container[--dstUpper] = suffix[2];1498} else1499System.arraycopy(suffix, 0, container, startIndex, len);15001501fastPathData.lastFreeIndex += len;1502}15031504/**1505* Converts digit chars from {@code digitsBuffer} to current locale.1506*1507* Must be called before adding affixes since we refer to1508* {@code fastPathData.firstUsedIndex} and {@code fastPathData.lastFreeIndex},1509* and do not support affixes (for speed reason).1510*1511* We loop backward starting from last used index in {@code fastPathData}.1512*1513* @param digitsBuffer The char array container where the digits are stored.1514*/1515private void localizeDigits(char[] digitsBuffer) {15161517// We will localize only the digits, using the groupingSize,1518// and taking into account fractional part.15191520// First take into account fractional part.1521int digitsCounter =1522fastPathData.lastFreeIndex - fastPathData.fractionalFirstIndex;15231524// The case when there is no fractional digits.1525if (digitsCounter < 0)1526digitsCounter = groupingSize;15271528// Only the digits remains to localize.1529for (int cursor = fastPathData.lastFreeIndex - 1;1530cursor >= fastPathData.firstUsedIndex;1531cursor--) {1532if (digitsCounter != 0) {1533// This is a digit char, we must localize it.1534digitsBuffer[cursor] += fastPathData.zeroDelta;1535digitsCounter--;1536} else {1537// Decimal separator or grouping char. Reinit counter only.1538digitsCounter = groupingSize;1539}1540}1541}15421543/**1544* This is the main entry point for the fast-path format algorithm.1545*1546* At this point we are sure to be in the expected conditions to run it.1547* This algorithm builds the formatted result and puts it in the dedicated1548* {@code fastPathData.fastPathContainer}.1549*1550* @param d the double value to be formatted.1551* @param negative Flag precising if {@code d} is negative.1552*/1553private void fastDoubleFormat(double d,1554boolean negative) {15551556char[] container = fastPathData.fastPathContainer;15571558/*1559* The principle of the algorithm is to :1560* - Break the passed double into its integral and fractional parts1561* converted into integers.1562* - Then decide if rounding up must be applied or not by following1563* the half-even rounding rule, first using approximated scaled1564* fractional part.1565* - For the difficult cases (approximated scaled fractional part1566* being exactly 0.5d), we refine the rounding decision by calling1567* exactRoundUp utility method that both calculates the exact roundoff1568* on the approximation and takes correct rounding decision.1569* - We round-up the fractional part if needed, possibly propagating the1570* rounding to integral part if we meet a "all-nine" case for the1571* scaled fractional part.1572* - We then collect digits from the resulting integral and fractional1573* parts, also setting the required grouping chars on the fly.1574* - Then we localize the collected digits if needed, and1575* - Finally prepend/append prefix/suffix if any is needed.1576*/15771578// Exact integral part of d.1579int integralPartAsInt = (int) d;15801581// Exact fractional part of d (since we subtract it's integral part).1582double exactFractionalPart = d - (double) integralPartAsInt;15831584// Approximated scaled fractional part of d (due to multiplication).1585double scaledFractional =1586exactFractionalPart * fastPathData.fractionalScaleFactor;15871588// Exact integral part of scaled fractional above.1589int fractionalPartAsInt = (int) scaledFractional;15901591// Exact fractional part of scaled fractional above.1592scaledFractional = scaledFractional - (double) fractionalPartAsInt;15931594// Only when scaledFractional is exactly 0.5d do we have to do exact1595// calculations and take fine-grained rounding decision, since1596// approximated results above may lead to incorrect decision.1597// Otherwise comparing against 0.5d (strictly greater or less) is ok.1598boolean roundItUp = false;1599if (scaledFractional >= 0.5d) {1600if (scaledFractional == 0.5d)1601// Rounding need fine-grained decision.1602roundItUp = exactRoundUp(exactFractionalPart, fractionalPartAsInt);1603else1604roundItUp = true;16051606if (roundItUp) {1607// Rounds up both fractional part (and also integral if needed).1608if (fractionalPartAsInt < fastPathData.fractionalMaxIntBound) {1609fractionalPartAsInt++;1610} else {1611// Propagates rounding to integral part since "all nines" case.1612fractionalPartAsInt = 0;1613integralPartAsInt++;1614}1615}1616}16171618// Collecting digits.1619collectFractionalDigits(fractionalPartAsInt, container,1620fastPathData.fractionalFirstIndex);1621collectIntegralDigits(integralPartAsInt, container,1622fastPathData.integralLastIndex);16231624// Localizing digits.1625if (fastPathData.zeroDelta != 0)1626localizeDigits(container);16271628// Adding prefix and suffix.1629if (negative) {1630if (fastPathData.negativeAffixesRequired)1631addAffixes(container,1632fastPathData.charsNegativePrefix,1633fastPathData.charsNegativeSuffix);1634} else if (fastPathData.positiveAffixesRequired)1635addAffixes(container,1636fastPathData.charsPositivePrefix,1637fastPathData.charsPositiveSuffix);1638}16391640/**1641* A fast-path shortcut of format(double) to be called by NumberFormat, or by1642* format(double, ...) public methods.1643*1644* If instance can be applied fast-path and passed double is not NaN or1645* Infinity, is in the integer range, we call {@code fastDoubleFormat}1646* after changing {@code d} to its positive value if necessary.1647*1648* Otherwise returns null by convention since fast-path can't be exercized.1649*1650* @param d The double value to be formatted1651*1652* @return the formatted result for {@code d} as a string.1653*/1654String fastFormat(double d) {1655boolean isDataSet = false;1656// (Re-)Evaluates fast-path status if needed.1657if (fastPathCheckNeeded) {1658isDataSet = checkAndSetFastPathStatus();1659}16601661if (!isFastPath )1662// DecimalFormat instance is not in a fast-path state.1663return null;16641665if (!Double.isFinite(d))1666// Should not use fast-path for Infinity and NaN.1667return null;16681669// Extracts and records sign of double value, possibly changing it1670// to a positive one, before calling fastDoubleFormat().1671boolean negative = false;1672if (d < 0.0d) {1673negative = true;1674d = -d;1675} else if (d == 0.0d) {1676negative = (Math.copySign(1.0d, d) == -1.0d);1677d = +0.0d;1678}16791680if (d > MAX_INT_AS_DOUBLE)1681// Filters out values that are outside expected fast-path range1682return null;1683else {1684if (!isDataSet) {1685/*1686* If the fast path data is not set through1687* checkAndSetFastPathStatus() and fulfil the1688* fast path conditions then reset the data1689* directly through resetFastPathData()1690*/1691resetFastPathData(isFastPath);1692}1693fastDoubleFormat(d, negative);16941695}169616971698// Returns a new string from updated fastPathContainer.1699return new String(fastPathData.fastPathContainer,1700fastPathData.firstUsedIndex,1701fastPathData.lastFreeIndex - fastPathData.firstUsedIndex);17021703}17041705/**1706* Sets the {@code DigitList} used by this {@code DecimalFormat}1707* instance.1708* @param number the number to format1709* @param isNegative true, if the number is negative; false otherwise1710* @param maxDigits the max digits1711*/1712void setDigitList(Number number, boolean isNegative, int maxDigits) {17131714if (number instanceof Double) {1715digitList.set(isNegative, (Double) number, maxDigits, true);1716} else if (number instanceof BigDecimal) {1717digitList.set(isNegative, (BigDecimal) number, maxDigits, true);1718} else if (number instanceof Long) {1719digitList.set(isNegative, (Long) number, maxDigits);1720} else if (number instanceof BigInteger) {1721digitList.set(isNegative, (BigInteger) number, maxDigits);1722}1723}17241725// ======== End fast-path formating logic for double =========================17261727/**1728* Complete the formatting of a finite number. On entry, the digitList must1729* be filled in with the correct digits.1730*/1731private StringBuffer subformat(StringBuffer result, FieldDelegate delegate,1732boolean isNegative, boolean isInteger,1733int maxIntDigits, int minIntDigits,1734int maxFraDigits, int minFraDigits) {17351736// Process prefix1737if (isNegative) {1738append(result, negativePrefix, delegate,1739getNegativePrefixFieldPositions(), Field.SIGN);1740} else {1741append(result, positivePrefix, delegate,1742getPositivePrefixFieldPositions(), Field.SIGN);1743}17441745// Process number1746subformatNumber(result, delegate, isNegative, isInteger,1747maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);17481749// Process suffix1750if (isNegative) {1751append(result, negativeSuffix, delegate,1752getNegativeSuffixFieldPositions(), Field.SIGN);1753} else {1754append(result, positiveSuffix, delegate,1755getPositiveSuffixFieldPositions(), Field.SIGN);1756}17571758return result;1759}17601761/**1762* Subformats number part using the {@code DigitList} of this1763* {@code DecimalFormat} instance.1764* @param result where the text is to be appended1765* @param delegate notified of the location of sub fields1766* @param isNegative true, if the number is negative; false otherwise1767* @param isInteger true, if the number is an integer; false otherwise1768* @param maxIntDigits maximum integer digits1769* @param minIntDigits minimum integer digits1770* @param maxFraDigits maximum fraction digits1771* @param minFraDigits minimum fraction digits1772*/1773void subformatNumber(StringBuffer result, FieldDelegate delegate,1774boolean isNegative, boolean isInteger,1775int maxIntDigits, int minIntDigits,1776int maxFraDigits, int minFraDigits) {17771778char grouping = isCurrencyFormat ?1779symbols.getMonetaryGroupingSeparator() :1780symbols.getGroupingSeparator();1781char zero = symbols.getZeroDigit();1782int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero17831784char decimal = isCurrencyFormat ?1785symbols.getMonetaryDecimalSeparator() :1786symbols.getDecimalSeparator();17871788/* Per bug 4147706, DecimalFormat must respect the sign of numbers which1789* format as zero. This allows sensible computations and preserves1790* relations such as signum(1/x) = signum(x), where x is +Infinity or1791* -Infinity. Prior to this fix, we always formatted zero values as if1792* they were positive. Liu 7/6/98.1793*/1794if (digitList.isZero()) {1795digitList.decimalAt = 0; // Normalize1796}17971798if (useExponentialNotation) {1799int iFieldStart = result.length();1800int iFieldEnd = -1;1801int fFieldStart = -1;18021803// Minimum integer digits are handled in exponential format by1804// adjusting the exponent. For example, 0.01234 with 3 minimum1805// integer digits is "123.4E-4".1806// Maximum integer digits are interpreted as indicating the1807// repeating range. This is useful for engineering notation, in1808// which the exponent is restricted to a multiple of 3. For1809// example, 0.01234 with 3 maximum integer digits is "12.34e-3".1810// If maximum integer digits are > 1 and are larger than1811// minimum integer digits, then minimum integer digits are1812// ignored.1813int exponent = digitList.decimalAt;1814int repeat = maxIntDigits;1815int minimumIntegerDigits = minIntDigits;1816if (repeat > 1 && repeat > minIntDigits) {1817// A repeating range is defined; adjust to it as follows.1818// If repeat == 3, we have 6,5,4=>3; 3,2,1=>0; 0,-1,-2=>-3;1819// -3,-4,-5=>-6, etc. This takes into account that the1820// exponent we have here is off by one from what we expect;1821// it is for the format 0.MMMMMx10^n.1822if (exponent >= 1) {1823exponent = ((exponent - 1) / repeat) * repeat;1824} else {1825// integer division rounds towards 01826exponent = ((exponent - repeat) / repeat) * repeat;1827}1828minimumIntegerDigits = 1;1829} else {1830// No repeating range is defined; use minimum integer digits.1831exponent -= minimumIntegerDigits;1832}18331834// We now output a minimum number of digits, and more if there1835// are more digits, up to the maximum number of digits. We1836// place the decimal point after the "integer" digits, which1837// are the first (decimalAt - exponent) digits.1838int minimumDigits = minIntDigits + minFraDigits;1839if (minimumDigits < 0) { // overflow?1840minimumDigits = Integer.MAX_VALUE;1841}18421843// The number of integer digits is handled specially if the number1844// is zero, since then there may be no digits.1845int integerDigits = digitList.isZero() ? minimumIntegerDigits :1846digitList.decimalAt - exponent;1847if (minimumDigits < integerDigits) {1848minimumDigits = integerDigits;1849}1850int totalDigits = digitList.count;1851if (minimumDigits > totalDigits) {1852totalDigits = minimumDigits;1853}1854boolean addedDecimalSeparator = false;18551856for (int i=0; i<totalDigits; ++i) {1857if (i == integerDigits) {1858// Record field information for caller.1859iFieldEnd = result.length();18601861result.append(decimal);1862addedDecimalSeparator = true;18631864// Record field information for caller.1865fFieldStart = result.length();1866}1867result.append((i < digitList.count) ?1868(char)(digitList.digits[i] + zeroDelta) :1869zero);1870}18711872if (decimalSeparatorAlwaysShown && totalDigits == integerDigits) {1873// Record field information for caller.1874iFieldEnd = result.length();18751876result.append(decimal);1877addedDecimalSeparator = true;18781879// Record field information for caller.1880fFieldStart = result.length();1881}18821883// Record field information1884if (iFieldEnd == -1) {1885iFieldEnd = result.length();1886}1887delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,1888iFieldStart, iFieldEnd, result);1889if (addedDecimalSeparator) {1890delegate.formatted(Field.DECIMAL_SEPARATOR,1891Field.DECIMAL_SEPARATOR,1892iFieldEnd, fFieldStart, result);1893}1894if (fFieldStart == -1) {1895fFieldStart = result.length();1896}1897delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION,1898fFieldStart, result.length(), result);18991900// The exponent is output using the pattern-specified minimum1901// exponent digits. There is no maximum limit to the exponent1902// digits, since truncating the exponent would result in an1903// unacceptable inaccuracy.1904int fieldStart = result.length();19051906result.append(symbols.getExponentSeparator());19071908delegate.formatted(Field.EXPONENT_SYMBOL, Field.EXPONENT_SYMBOL,1909fieldStart, result.length(), result);19101911// For zero values, we force the exponent to zero. We1912// must do this here, and not earlier, because the value1913// is used to determine integer digit count above.1914if (digitList.isZero()) {1915exponent = 0;1916}19171918boolean negativeExponent = exponent < 0;1919if (negativeExponent) {1920exponent = -exponent;1921fieldStart = result.length();1922result.append(symbols.getMinusSignText());1923delegate.formatted(Field.EXPONENT_SIGN, Field.EXPONENT_SIGN,1924fieldStart, result.length(), result);1925}1926digitList.set(negativeExponent, exponent);19271928int eFieldStart = result.length();19291930for (int i=digitList.decimalAt; i<minExponentDigits; ++i) {1931result.append(zero);1932}1933for (int i=0; i<digitList.decimalAt; ++i) {1934result.append((i < digitList.count) ?1935(char)(digitList.digits[i] + zeroDelta) : zero);1936}1937delegate.formatted(Field.EXPONENT, Field.EXPONENT, eFieldStart,1938result.length(), result);1939} else {1940int iFieldStart = result.length();19411942// Output the integer portion. Here 'count' is the total1943// number of integer digits we will display, including both1944// leading zeros required to satisfy getMinimumIntegerDigits,1945// and actual digits present in the number.1946int count = minIntDigits;1947int digitIndex = 0; // Index into digitList.fDigits[]1948if (digitList.decimalAt > 0 && count < digitList.decimalAt) {1949count = digitList.decimalAt;1950}19511952// Handle the case where getMaximumIntegerDigits() is smaller1953// than the real number of integer digits. If this is so, we1954// output the least significant max integer digits. For example,1955// the value 1997 printed with 2 max integer digits is just "97".1956if (count > maxIntDigits) {1957count = maxIntDigits;1958digitIndex = digitList.decimalAt - count;1959}19601961int sizeBeforeIntegerPart = result.length();1962for (int i=count-1; i>=0; --i) {1963if (i < digitList.decimalAt && digitIndex < digitList.count) {1964// Output a real digit1965result.append((char)(digitList.digits[digitIndex++] + zeroDelta));1966} else {1967// Output a leading zero1968result.append(zero);1969}19701971// Output grouping separator if necessary. Don't output a1972// grouping separator if i==0 though; that's at the end of1973// the integer part.1974if (isGroupingUsed() && i>0 && (groupingSize != 0) &&1975(i % groupingSize == 0)) {1976int gStart = result.length();1977result.append(grouping);1978delegate.formatted(Field.GROUPING_SEPARATOR,1979Field.GROUPING_SEPARATOR, gStart,1980result.length(), result);1981}1982}19831984// Determine whether or not there are any printable fractional1985// digits. If we've used up the digits we know there aren't.1986boolean fractionPresent = (minFraDigits > 0) ||1987(!isInteger && digitIndex < digitList.count);19881989// If there is no fraction present, and we haven't printed any1990// integer digits, then print a zero. Otherwise we won't print1991// _any_ digits, and we won't be able to parse this string.1992if (!fractionPresent && result.length() == sizeBeforeIntegerPart) {1993result.append(zero);1994}19951996delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,1997iFieldStart, result.length(), result);19981999// Output the decimal separator if we always do so.2000int sStart = result.length();2001if (decimalSeparatorAlwaysShown || fractionPresent) {2002result.append(decimal);2003}20042005if (sStart != result.length()) {2006delegate.formatted(Field.DECIMAL_SEPARATOR,2007Field.DECIMAL_SEPARATOR,2008sStart, result.length(), result);2009}2010int fFieldStart = result.length();20112012for (int i=0; i < maxFraDigits; ++i) {2013// Here is where we escape from the loop. We escape if we've2014// output the maximum fraction digits (specified in the for2015// expression above).2016// We also stop when we've output the minimum digits and either:2017// we have an integer, so there is no fractional stuff to2018// display, or we're out of significant digits.2019if (i >= minFraDigits &&2020(isInteger || digitIndex >= digitList.count)) {2021break;2022}20232024// Output leading fractional zeros. These are zeros that come2025// after the decimal but before any significant digits. These2026// are only output if abs(number being formatted) < 1.0.2027if (-1-i > (digitList.decimalAt-1)) {2028result.append(zero);2029continue;2030}20312032// Output a digit, if we have any precision left, or a2033// zero if we don't. We don't want to output noise digits.2034if (!isInteger && digitIndex < digitList.count) {2035result.append((char)(digitList.digits[digitIndex++] + zeroDelta));2036} else {2037result.append(zero);2038}2039}20402041// Record field information for caller.2042delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION,2043fFieldStart, result.length(), result);2044}2045}20462047/**2048* Appends the String {@code string} to {@code result}.2049* {@code delegate} is notified of all the2050* {@code FieldPosition}s in {@code positions}.2051* <p>2052* If one of the {@code FieldPosition}s in {@code positions}2053* identifies a {@code SIGN} attribute, it is mapped to2054* {@code signAttribute}. This is used2055* to map the {@code SIGN} attribute to the {@code EXPONENT}2056* attribute as necessary.2057* <p>2058* This is used by {@code subformat} to add the prefix/suffix.2059*/2060private void append(StringBuffer result, String string,2061FieldDelegate delegate,2062FieldPosition[] positions,2063Format.Field signAttribute) {2064int start = result.length();20652066if (!string.isEmpty()) {2067result.append(string);2068for (int counter = 0, max = positions.length; counter < max;2069counter++) {2070FieldPosition fp = positions[counter];2071Format.Field attribute = fp.getFieldAttribute();20722073if (attribute == Field.SIGN) {2074attribute = signAttribute;2075}2076delegate.formatted(attribute, attribute,2077start + fp.getBeginIndex(),2078start + fp.getEndIndex(), result);2079}2080}2081}20822083/**2084* Parses text from a string to produce a {@code Number}.2085* <p>2086* The method attempts to parse text starting at the index given by2087* {@code pos}.2088* If parsing succeeds, then the index of {@code pos} is updated2089* to the index after the last character used (parsing does not necessarily2090* use all characters up to the end of the string), and the parsed2091* number is returned. The updated {@code pos} can be used to2092* indicate the starting point for the next call to this method.2093* If an error occurs, then the index of {@code pos} is not2094* changed, the error index of {@code pos} is set to the index of2095* the character where the error occurred, and null is returned.2096* <p>2097* The subclass returned depends on the value of {@link #isParseBigDecimal}2098* as well as on the string being parsed.2099* <ul>2100* <li>If {@code isParseBigDecimal()} is false (the default),2101* most integer values are returned as {@code Long}2102* objects, no matter how they are written: {@code "17"} and2103* {@code "17.000"} both parse to {@code Long(17)}.2104* Values that cannot fit into a {@code Long} are returned as2105* {@code Double}s. This includes values with a fractional part,2106* infinite values, {@code NaN}, and the value -0.0.2107* {@code DecimalFormat} does <em>not</em> decide whether to2108* return a {@code Double} or a {@code Long} based on the2109* presence of a decimal separator in the source string. Doing so2110* would prevent integers that overflow the mantissa of a double,2111* such as {@code "-9,223,372,036,854,775,808.00"}, from being2112* parsed accurately.2113* <p>2114* Callers may use the {@code Number} methods2115* {@code doubleValue}, {@code longValue}, etc., to obtain2116* the type they want.2117* <li>If {@code isParseBigDecimal()} is true, values are returned2118* as {@code BigDecimal} objects. The values are the ones2119* constructed by {@link java.math.BigDecimal#BigDecimal(String)}2120* for corresponding strings in locale-independent format. The2121* special cases negative and positive infinity and NaN are returned2122* as {@code Double} instances holding the values of the2123* corresponding {@code Double} constants.2124* </ul>2125* <p>2126* {@code DecimalFormat} parses all Unicode characters that represent2127* decimal digits, as defined by {@code Character.digit()}. In2128* addition, {@code DecimalFormat} also recognizes as digits the ten2129* consecutive characters starting with the localized zero digit defined in2130* the {@code DecimalFormatSymbols} object.2131*2132* @param text the string to be parsed2133* @param pos A {@code ParsePosition} object with index and error2134* index information as described above.2135* @return the parsed value, or {@code null} if the parse fails2136* @throws NullPointerException if {@code text} or2137* {@code pos} is null.2138*/2139@Override2140public Number parse(String text, ParsePosition pos) {2141// special case NaN2142if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols.getNaN().length())) {2143pos.index = pos.index + symbols.getNaN().length();2144return Double.valueOf(Double.NaN);2145}21462147boolean[] status = new boolean[STATUS_LENGTH];2148if (!subparse(text, pos, positivePrefix, negativePrefix, digitList, false, status)) {2149return null;2150}21512152// special case INFINITY2153if (status[STATUS_INFINITE]) {2154if (status[STATUS_POSITIVE] == (multiplier >= 0)) {2155return Double.valueOf(Double.POSITIVE_INFINITY);2156} else {2157return Double.valueOf(Double.NEGATIVE_INFINITY);2158}2159}21602161if (multiplier == 0) {2162if (digitList.isZero()) {2163return Double.valueOf(Double.NaN);2164} else if (status[STATUS_POSITIVE]) {2165return Double.valueOf(Double.POSITIVE_INFINITY);2166} else {2167return Double.valueOf(Double.NEGATIVE_INFINITY);2168}2169}21702171if (isParseBigDecimal()) {2172BigDecimal bigDecimalResult = digitList.getBigDecimal();21732174if (multiplier != 1) {2175try {2176bigDecimalResult = bigDecimalResult.divide(getBigDecimalMultiplier());2177}2178catch (ArithmeticException e) { // non-terminating decimal expansion2179bigDecimalResult = bigDecimalResult.divide(getBigDecimalMultiplier(), roundingMode);2180}2181}21822183if (!status[STATUS_POSITIVE]) {2184bigDecimalResult = bigDecimalResult.negate();2185}2186return bigDecimalResult;2187} else {2188boolean gotDouble = true;2189boolean gotLongMinimum = false;2190double doubleResult = 0.0;2191long longResult = 0;21922193// Finally, have DigitList parse the digits into a value.2194if (digitList.fitsIntoLong(status[STATUS_POSITIVE], isParseIntegerOnly())) {2195gotDouble = false;2196longResult = digitList.getLong();2197if (longResult < 0) { // got Long.MIN_VALUE2198gotLongMinimum = true;2199}2200} else {2201doubleResult = digitList.getDouble();2202}22032204// Divide by multiplier. We have to be careful here not to do2205// unneeded conversions between double and long.2206if (multiplier != 1) {2207if (gotDouble) {2208doubleResult /= multiplier;2209} else {2210// Avoid converting to double if we can2211if (longResult % multiplier == 0) {2212longResult /= multiplier;2213} else {2214doubleResult = ((double)longResult) / multiplier;2215gotDouble = true;2216}2217}2218}22192220if (!status[STATUS_POSITIVE] && !gotLongMinimum) {2221doubleResult = -doubleResult;2222longResult = -longResult;2223}22242225// At this point, if we divided the result by the multiplier, the2226// result may fit into a long. We check for this case and return2227// a long if possible.2228// We must do this AFTER applying the negative (if appropriate)2229// in order to handle the case of LONG_MIN; otherwise, if we do2230// this with a positive value -LONG_MIN, the double is > 0, but2231// the long is < 0. We also must retain a double in the case of2232// -0.0, which will compare as == to a long 0 cast to a double2233// (bug 4162852).2234if (multiplier != 1 && gotDouble) {2235longResult = (long)doubleResult;2236gotDouble = ((doubleResult != (double)longResult) ||2237(doubleResult == 0.0 && 1/doubleResult < 0.0)) &&2238!isParseIntegerOnly();2239}22402241// cast inside of ?: because of binary numeric promotion, JLS 15.252242return gotDouble ? (Number)doubleResult : (Number)longResult;2243}2244}22452246/**2247* Return a BigInteger multiplier.2248*/2249private BigInteger getBigIntegerMultiplier() {2250if (bigIntegerMultiplier == null) {2251bigIntegerMultiplier = BigInteger.valueOf(multiplier);2252}2253return bigIntegerMultiplier;2254}2255private transient BigInteger bigIntegerMultiplier;22562257/**2258* Return a BigDecimal multiplier.2259*/2260private BigDecimal getBigDecimalMultiplier() {2261if (bigDecimalMultiplier == null) {2262bigDecimalMultiplier = new BigDecimal(multiplier);2263}2264return bigDecimalMultiplier;2265}2266private transient BigDecimal bigDecimalMultiplier;22672268private static final int STATUS_INFINITE = 0;2269private static final int STATUS_POSITIVE = 1;2270private static final int STATUS_LENGTH = 2;22712272/**2273* Parse the given text into a number. The text is parsed beginning at2274* parsePosition, until an unparseable character is seen.2275* @param text The string to parse.2276* @param parsePosition The position at which to being parsing. Upon2277* return, the first unparseable character.2278* @param digits The DigitList to set to the parsed value.2279* @param isExponent If true, parse an exponent. This means no2280* infinite values and integer only.2281* @param status Upon return contains boolean status flags indicating2282* whether the value was infinite and whether it was positive.2283*/2284private final boolean subparse(String text, ParsePosition parsePosition,2285String positivePrefix, String negativePrefix,2286DigitList digits, boolean isExponent,2287boolean status[]) {2288int position = parsePosition.index;2289int oldStart = parsePosition.index;2290boolean gotPositive, gotNegative;22912292// check for positivePrefix; take longest2293gotPositive = text.regionMatches(position, positivePrefix, 0,2294positivePrefix.length());2295gotNegative = text.regionMatches(position, negativePrefix, 0,2296negativePrefix.length());22972298if (gotPositive && gotNegative) {2299if (positivePrefix.length() > negativePrefix.length()) {2300gotNegative = false;2301} else if (positivePrefix.length() < negativePrefix.length()) {2302gotPositive = false;2303}2304}23052306if (gotPositive) {2307position += positivePrefix.length();2308} else if (gotNegative) {2309position += negativePrefix.length();2310} else {2311parsePosition.errorIndex = position;2312return false;2313}23142315position = subparseNumber(text, position, digits, true, isExponent, status);2316if (position == -1) {2317parsePosition.index = oldStart;2318parsePosition.errorIndex = oldStart;2319return false;2320}23212322// Check for suffix2323if (!isExponent) {2324if (gotPositive) {2325gotPositive = text.regionMatches(position,positiveSuffix,0,2326positiveSuffix.length());2327}2328if (gotNegative) {2329gotNegative = text.regionMatches(position,negativeSuffix,0,2330negativeSuffix.length());2331}23322333// If both match, take longest2334if (gotPositive && gotNegative) {2335if (positiveSuffix.length() > negativeSuffix.length()) {2336gotNegative = false;2337} else if (positiveSuffix.length() < negativeSuffix.length()) {2338gotPositive = false;2339}2340}23412342// Fail if neither or both2343if (gotPositive == gotNegative) {2344parsePosition.errorIndex = position;2345return false;2346}23472348parsePosition.index = position +2349(gotPositive ? positiveSuffix.length() : negativeSuffix.length()); // mark success!2350} else {2351parsePosition.index = position;2352}23532354status[STATUS_POSITIVE] = gotPositive;2355if (parsePosition.index == oldStart) {2356parsePosition.errorIndex = position;2357return false;2358}2359return true;2360}23612362/**2363* Parses a number from the given {@code text}. The text is parsed2364* beginning at position, until an unparseable character is seen.2365*2366* @param text the string to parse2367* @param position the position at which parsing begins2368* @param digits the DigitList to set to the parsed value2369* @param checkExponent whether to check for exponential number2370* @param isExponent if the exponential part is encountered2371* @param status upon return contains boolean status flags indicating2372* whether the value is infinite and whether it is2373* positive2374* @return returns the position of the first unparseable character or2375* -1 in case of no valid number parsed2376*/2377int subparseNumber(String text, int position,2378DigitList digits, boolean checkExponent,2379boolean isExponent, boolean status[]) {2380// process digits or Inf, find decimal position2381status[STATUS_INFINITE] = false;2382if (!isExponent && text.regionMatches(position,symbols.getInfinity(),0,2383symbols.getInfinity().length())) {2384position += symbols.getInfinity().length();2385status[STATUS_INFINITE] = true;2386} else {2387// We now have a string of digits, possibly with grouping symbols,2388// and decimal points. We want to process these into a DigitList.2389// We don't want to put a bunch of leading zeros into the DigitList2390// though, so we keep track of the location of the decimal point,2391// put only significant digits into the DigitList, and adjust the2392// exponent as needed.23932394digits.decimalAt = digits.count = 0;2395char zero = symbols.getZeroDigit();2396char decimal = isCurrencyFormat ?2397symbols.getMonetaryDecimalSeparator() :2398symbols.getDecimalSeparator();2399char grouping = isCurrencyFormat ?2400symbols.getMonetaryGroupingSeparator() :2401symbols.getGroupingSeparator();2402String exponentString = symbols.getExponentSeparator();2403boolean sawDecimal = false;2404boolean sawExponent = false;2405boolean sawDigit = false;2406int exponent = 0; // Set to the exponent value, if any24072408// We have to track digitCount ourselves, because digits.count will2409// pin when the maximum allowable digits is reached.2410int digitCount = 0;24112412int backup = -1;2413for (; position < text.length(); ++position) {2414char ch = text.charAt(position);24152416/* We recognize all digit ranges, not only the Latin digit range2417* '0'..'9'. We do so by using the Character.digit() method,2418* which converts a valid Unicode digit to the range 0..9.2419*2420* The character 'ch' may be a digit. If so, place its value2421* from 0 to 9 in 'digit'. First try using the locale digit,2422* which may or MAY NOT be a standard Unicode digit range. If2423* this fails, try using the standard Unicode digit ranges by2424* calling Character.digit(). If this also fails, digit will2425* have a value outside the range 0..9.2426*/2427int digit = ch - zero;2428if (digit < 0 || digit > 9) {2429digit = Character.digit(ch, 10);2430}24312432if (digit == 0) {2433// Cancel out backup setting (see grouping handler below)2434backup = -1; // Do this BEFORE continue statement below!!!2435sawDigit = true;24362437// Handle leading zeros2438if (digits.count == 0) {2439// Ignore leading zeros in integer part of number.2440if (!sawDecimal) {2441continue;2442}24432444// If we have seen the decimal, but no significant2445// digits yet, then we account for leading zeros by2446// decrementing the digits.decimalAt into negative2447// values.2448--digits.decimalAt;2449} else {2450++digitCount;2451digits.append((char)(digit + '0'));2452}2453} else if (digit > 0 && digit <= 9) { // [sic] digit==0 handled above2454sawDigit = true;2455++digitCount;2456digits.append((char)(digit + '0'));24572458// Cancel out backup setting (see grouping handler below)2459backup = -1;2460} else if (!isExponent && ch == decimal) {2461// If we're only parsing integers, or if we ALREADY saw the2462// decimal, then don't parse this one.2463if (isParseIntegerOnly() || sawDecimal) {2464break;2465}2466digits.decimalAt = digitCount; // Not digits.count!2467sawDecimal = true;2468} else if (!isExponent && ch == grouping && isGroupingUsed()) {2469if (sawDecimal) {2470break;2471}2472// Ignore grouping characters, if we are using them, but2473// require that they be followed by a digit. Otherwise2474// we backup and reprocess them.2475backup = position;2476} else if (checkExponent && !isExponent && text.regionMatches(position, exponentString, 0, exponentString.length())2477&& !sawExponent) {2478// Process the exponent by recursively calling this method.2479ParsePosition pos = new ParsePosition(position + exponentString.length());2480boolean[] stat = new boolean[STATUS_LENGTH];2481DigitList exponentDigits = new DigitList();24822483if (subparse(text, pos, "", symbols.getMinusSignText(), exponentDigits, true, stat) &&2484exponentDigits.fitsIntoLong(stat[STATUS_POSITIVE], true)) {2485position = pos.index; // Advance past the exponent2486exponent = (int)exponentDigits.getLong();2487if (!stat[STATUS_POSITIVE]) {2488exponent = -exponent;2489}2490sawExponent = true;2491}2492break; // Whether we fail or succeed, we exit this loop2493} else {2494break;2495}2496}24972498if (backup != -1) {2499position = backup;2500}25012502// If there was no decimal point we have an integer2503if (!sawDecimal) {2504digits.decimalAt = digitCount; // Not digits.count!2505}25062507// Adjust for exponent, if any2508digits.decimalAt += exponent;25092510// If none of the text string was recognized. For example, parse2511// "x" with pattern "#0.00" (return index and error index both 0)2512// parse "$" with pattern "$#0.00". (return index 0 and error2513// index 1).2514if (!sawDigit && digitCount == 0) {2515return -1;2516}2517}2518return position;25192520}25212522/**2523* Returns a copy of the decimal format symbols, which is generally not2524* changed by the programmer or user.2525* @return a copy of the desired DecimalFormatSymbols2526* @see java.text.DecimalFormatSymbols2527*/2528public DecimalFormatSymbols getDecimalFormatSymbols() {2529try {2530// don't allow multiple references2531return (DecimalFormatSymbols) symbols.clone();2532} catch (Exception foo) {2533return null; // should never happen2534}2535}253625372538/**2539* Sets the decimal format symbols, which is generally not changed2540* by the programmer or user.2541* @param newSymbols desired DecimalFormatSymbols2542* @see java.text.DecimalFormatSymbols2543*/2544public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {2545try {2546// don't allow multiple references2547symbols = (DecimalFormatSymbols) newSymbols.clone();2548expandAffixes();2549fastPathCheckNeeded = true;2550} catch (Exception foo) {2551// should never happen2552}2553}25542555/**2556* Get the positive prefix.2557* <P>Examples: +123, $123, sFr1232558*2559* @return the positive prefix2560*/2561public String getPositivePrefix () {2562return positivePrefix;2563}25642565/**2566* Set the positive prefix.2567* <P>Examples: +123, $123, sFr1232568*2569* @param newValue the new positive prefix2570*/2571public void setPositivePrefix (String newValue) {2572positivePrefix = newValue;2573posPrefixPattern = null;2574positivePrefixFieldPositions = null;2575fastPathCheckNeeded = true;2576}25772578/**2579* Returns the FieldPositions of the fields in the prefix used for2580* positive numbers. This is not used if the user has explicitly set2581* a positive prefix via {@code setPositivePrefix}. This is2582* lazily created.2583*2584* @return FieldPositions in positive prefix2585*/2586private FieldPosition[] getPositivePrefixFieldPositions() {2587if (positivePrefixFieldPositions == null) {2588if (posPrefixPattern != null) {2589positivePrefixFieldPositions = expandAffix(posPrefixPattern);2590} else {2591positivePrefixFieldPositions = EmptyFieldPositionArray;2592}2593}2594return positivePrefixFieldPositions;2595}25962597/**2598* Get the negative prefix.2599* <P>Examples: -123, ($123) (with negative suffix), sFr-1232600*2601* @return the negative prefix2602*/2603public String getNegativePrefix () {2604return negativePrefix;2605}26062607/**2608* Set the negative prefix.2609* <P>Examples: -123, ($123) (with negative suffix), sFr-1232610*2611* @param newValue the new negative prefix2612*/2613public void setNegativePrefix (String newValue) {2614negativePrefix = newValue;2615negPrefixPattern = null;2616fastPathCheckNeeded = true;2617}26182619/**2620* Returns the FieldPositions of the fields in the prefix used for2621* negative numbers. This is not used if the user has explicitly set2622* a negative prefix via {@code setNegativePrefix}. This is2623* lazily created.2624*2625* @return FieldPositions in positive prefix2626*/2627private FieldPosition[] getNegativePrefixFieldPositions() {2628if (negativePrefixFieldPositions == null) {2629if (negPrefixPattern != null) {2630negativePrefixFieldPositions = expandAffix(negPrefixPattern);2631} else {2632negativePrefixFieldPositions = EmptyFieldPositionArray;2633}2634}2635return negativePrefixFieldPositions;2636}26372638/**2639* Get the positive suffix.2640* <P>Example: 123%2641*2642* @return the positive suffix2643*/2644public String getPositiveSuffix () {2645return positiveSuffix;2646}26472648/**2649* Set the positive suffix.2650* <P>Example: 123%2651*2652* @param newValue the new positive suffix2653*/2654public void setPositiveSuffix (String newValue) {2655positiveSuffix = newValue;2656posSuffixPattern = null;2657fastPathCheckNeeded = true;2658}26592660/**2661* Returns the FieldPositions of the fields in the suffix used for2662* positive numbers. This is not used if the user has explicitly set2663* a positive suffix via {@code setPositiveSuffix}. This is2664* lazily created.2665*2666* @return FieldPositions in positive prefix2667*/2668private FieldPosition[] getPositiveSuffixFieldPositions() {2669if (positiveSuffixFieldPositions == null) {2670if (posSuffixPattern != null) {2671positiveSuffixFieldPositions = expandAffix(posSuffixPattern);2672} else {2673positiveSuffixFieldPositions = EmptyFieldPositionArray;2674}2675}2676return positiveSuffixFieldPositions;2677}26782679/**2680* Get the negative suffix.2681* <P>Examples: -123%, ($123) (with positive suffixes)2682*2683* @return the negative suffix2684*/2685public String getNegativeSuffix () {2686return negativeSuffix;2687}26882689/**2690* Set the negative suffix.2691* <P>Examples: 123%2692*2693* @param newValue the new negative suffix2694*/2695public void setNegativeSuffix (String newValue) {2696negativeSuffix = newValue;2697negSuffixPattern = null;2698fastPathCheckNeeded = true;2699}27002701/**2702* Returns the FieldPositions of the fields in the suffix used for2703* negative numbers. This is not used if the user has explicitly set2704* a negative suffix via {@code setNegativeSuffix}. This is2705* lazily created.2706*2707* @return FieldPositions in positive prefix2708*/2709private FieldPosition[] getNegativeSuffixFieldPositions() {2710if (negativeSuffixFieldPositions == null) {2711if (negSuffixPattern != null) {2712negativeSuffixFieldPositions = expandAffix(negSuffixPattern);2713} else {2714negativeSuffixFieldPositions = EmptyFieldPositionArray;2715}2716}2717return negativeSuffixFieldPositions;2718}27192720/**2721* Gets the multiplier for use in percent, per mille, and similar2722* formats.2723*2724* @return the multiplier2725* @see #setMultiplier(int)2726*/2727public int getMultiplier () {2728return multiplier;2729}27302731/**2732* Sets the multiplier for use in percent, per mille, and similar2733* formats.2734* For a percent format, set the multiplier to 100 and the suffixes to2735* have '%' (for Arabic, use the Arabic percent sign).2736* For a per mille format, set the multiplier to 1000 and the suffixes to2737* have '\u2030'.2738*2739* <P>Example: with multiplier 100, 1.23 is formatted as "123", and2740* "123" is parsed into 1.23.2741*2742* @param newValue the new multiplier2743* @see #getMultiplier2744*/2745public void setMultiplier (int newValue) {2746multiplier = newValue;2747bigDecimalMultiplier = null;2748bigIntegerMultiplier = null;2749fastPathCheckNeeded = true;2750}27512752/**2753* {@inheritDoc}2754*/2755@Override2756public void setGroupingUsed(boolean newValue) {2757super.setGroupingUsed(newValue);2758fastPathCheckNeeded = true;2759}27602761/**2762* Return the grouping size. Grouping size is the number of digits between2763* grouping separators in the integer portion of a number. For example,2764* in the number "123,456.78", the grouping size is 3. Grouping size of2765* zero designates that grouping is not used, which provides the same2766* formatting as if calling {@link #setGroupingUsed(boolean)2767* setGroupingUsed(false)}.2768*2769* @return the grouping size2770* @see #setGroupingSize2771* @see java.text.NumberFormat#isGroupingUsed2772* @see java.text.DecimalFormatSymbols#getGroupingSeparator2773*/2774public int getGroupingSize () {2775return groupingSize;2776}27772778/**2779* Set the grouping size. Grouping size is the number of digits between2780* grouping separators in the integer portion of a number. For example,2781* in the number "123,456.78", the grouping size is 3. Grouping size of2782* zero designates that grouping is not used, which provides the same2783* formatting as if calling {@link #setGroupingUsed(boolean)2784* setGroupingUsed(false)}.2785* <p>2786* The value passed in is converted to a byte, which may lose information.2787* Values that are negative or greater than2788* {@link java.lang.Byte#MAX_VALUE Byte.MAX_VALUE}, will throw an2789* {@code IllegalArgumentException}.2790*2791* @param newValue the new grouping size2792* @see #getGroupingSize2793* @see java.text.NumberFormat#setGroupingUsed2794* @see java.text.DecimalFormatSymbols#setGroupingSeparator2795* @throws IllegalArgumentException if {@code newValue} is negative or2796* greater than {@link java.lang.Byte#MAX_VALUE Byte.MAX_VALUE}2797*/2798public void setGroupingSize (int newValue) {2799if (newValue < 0 || newValue > Byte.MAX_VALUE) {2800throw new IllegalArgumentException(2801"newValue is out of valid range. value: " + newValue);2802}2803groupingSize = (byte)newValue;2804fastPathCheckNeeded = true;2805}28062807/**2808* Allows you to get the behavior of the decimal separator with integers.2809* (The decimal separator will always appear with decimals.)2810* <P>Example: Decimal ON: 12345 → 12345.; OFF: 12345 → 123452811*2812* @return {@code true} if the decimal separator is always shown;2813* {@code false} otherwise2814*/2815public boolean isDecimalSeparatorAlwaysShown() {2816return decimalSeparatorAlwaysShown;2817}28182819/**2820* Allows you to set the behavior of the decimal separator with integers.2821* (The decimal separator will always appear with decimals.)2822* <P>Example: Decimal ON: 12345 → 12345.; OFF: 12345 → 123452823*2824* @param newValue {@code true} if the decimal separator is always shown;2825* {@code false} otherwise2826*/2827public void setDecimalSeparatorAlwaysShown(boolean newValue) {2828decimalSeparatorAlwaysShown = newValue;2829fastPathCheckNeeded = true;2830}28312832/**2833* Returns whether the {@link #parse(java.lang.String, java.text.ParsePosition)}2834* method returns {@code BigDecimal}. The default value is false.2835*2836* @return {@code true} if the parse method returns BigDecimal;2837* {@code false} otherwise2838* @see #setParseBigDecimal2839* @since 1.52840*/2841public boolean isParseBigDecimal() {2842return parseBigDecimal;2843}28442845/**2846* Sets whether the {@link #parse(java.lang.String, java.text.ParsePosition)}2847* method returns {@code BigDecimal}.2848*2849* @param newValue {@code true} if the parse method returns BigDecimal;2850* {@code false} otherwise2851* @see #isParseBigDecimal2852* @since 1.52853*/2854public void setParseBigDecimal(boolean newValue) {2855parseBigDecimal = newValue;2856}28572858/**2859* Standard override; no change in semantics.2860*/2861@Override2862public Object clone() {2863DecimalFormat other = (DecimalFormat) super.clone();2864other.symbols = (DecimalFormatSymbols) symbols.clone();2865other.digitList = (DigitList) digitList.clone();28662867// Fast-path is almost stateless algorithm. The only logical state is the2868// isFastPath flag. In addition fastPathCheckNeeded is a sentinel flag2869// that forces recalculation of all fast-path fields when set to true.2870//2871// There is thus no need to clone all the fast-path fields.2872// We just only need to set fastPathCheckNeeded to true when cloning,2873// and init fastPathData to null as if it were a truly new instance.2874// Every fast-path field will be recalculated (only once) at next usage of2875// fast-path algorithm.2876other.fastPathCheckNeeded = true;2877other.isFastPath = false;2878other.fastPathData = null;28792880return other;2881}28822883/**2884* Overrides equals2885*/2886@Override2887public boolean equals(Object obj)2888{2889if (obj == null)2890return false;2891if (!super.equals(obj))2892return false; // super does class check2893DecimalFormat other = (DecimalFormat) obj;2894return ((posPrefixPattern == other.posPrefixPattern &&2895positivePrefix.equals(other.positivePrefix))2896|| (posPrefixPattern != null &&2897posPrefixPattern.equals(other.posPrefixPattern)))2898&& ((posSuffixPattern == other.posSuffixPattern &&2899positiveSuffix.equals(other.positiveSuffix))2900|| (posSuffixPattern != null &&2901posSuffixPattern.equals(other.posSuffixPattern)))2902&& ((negPrefixPattern == other.negPrefixPattern &&2903negativePrefix.equals(other.negativePrefix))2904|| (negPrefixPattern != null &&2905negPrefixPattern.equals(other.negPrefixPattern)))2906&& ((negSuffixPattern == other.negSuffixPattern &&2907negativeSuffix.equals(other.negativeSuffix))2908|| (negSuffixPattern != null &&2909negSuffixPattern.equals(other.negSuffixPattern)))2910&& multiplier == other.multiplier2911&& groupingSize == other.groupingSize2912&& decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown2913&& parseBigDecimal == other.parseBigDecimal2914&& useExponentialNotation == other.useExponentialNotation2915&& (!useExponentialNotation ||2916minExponentDigits == other.minExponentDigits)2917&& maximumIntegerDigits == other.maximumIntegerDigits2918&& minimumIntegerDigits == other.minimumIntegerDigits2919&& maximumFractionDigits == other.maximumFractionDigits2920&& minimumFractionDigits == other.minimumFractionDigits2921&& roundingMode == other.roundingMode2922&& symbols.equals(other.symbols);2923}29242925/**2926* Overrides hashCode2927*/2928@Override2929public int hashCode() {2930return super.hashCode() * 37 + positivePrefix.hashCode();2931// just enough fields for a reasonable distribution2932}29332934/**2935* Synthesizes a pattern string that represents the current state2936* of this Format object.2937*2938* @return a pattern string2939* @see #applyPattern2940*/2941public String toPattern() {2942return toPattern( false );2943}29442945/**2946* Synthesizes a localized pattern string that represents the current2947* state of this Format object.2948*2949* @return a localized pattern string2950* @see #applyPattern2951*/2952public String toLocalizedPattern() {2953return toPattern( true );2954}29552956/**2957* Expand the affix pattern strings into the expanded affix strings. If any2958* affix pattern string is null, do not expand it. This method should be2959* called any time the symbols or the affix patterns change in order to keep2960* the expanded affix strings up to date.2961*/2962private void expandAffixes() {2963// Reuse one StringBuffer for better performance2964StringBuffer buffer = new StringBuffer();2965if (posPrefixPattern != null) {2966positivePrefix = expandAffix(posPrefixPattern, buffer);2967positivePrefixFieldPositions = null;2968}2969if (posSuffixPattern != null) {2970positiveSuffix = expandAffix(posSuffixPattern, buffer);2971positiveSuffixFieldPositions = null;2972}2973if (negPrefixPattern != null) {2974negativePrefix = expandAffix(negPrefixPattern, buffer);2975negativePrefixFieldPositions = null;2976}2977if (negSuffixPattern != null) {2978negativeSuffix = expandAffix(negSuffixPattern, buffer);2979negativeSuffixFieldPositions = null;2980}2981}29822983/**2984* Expand an affix pattern into an affix string. All characters in the2985* pattern are literal unless prefixed by QUOTE. The following characters2986* after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,2987* PATTERN_MINUS, and CURRENCY_SIGN. If CURRENCY_SIGN is doubled (QUOTE +2988* CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 42172989* currency code. Any other character after a QUOTE represents itself.2990* QUOTE must be followed by another character; QUOTE may not occur by2991* itself at the end of the pattern.2992*2993* @param pattern the non-null, possibly empty pattern2994* @param buffer a scratch StringBuffer; its contents will be lost2995* @return the expanded equivalent of pattern2996*/2997private String expandAffix(String pattern, StringBuffer buffer) {2998buffer.setLength(0);2999for (int i=0; i<pattern.length(); ) {3000char c = pattern.charAt(i++);3001if (c == QUOTE) {3002c = pattern.charAt(i++);3003switch (c) {3004case CURRENCY_SIGN:3005if (i<pattern.length() &&3006pattern.charAt(i) == CURRENCY_SIGN) {3007++i;3008buffer.append(symbols.getInternationalCurrencySymbol());3009} else {3010buffer.append(symbols.getCurrencySymbol());3011}3012continue;3013case PATTERN_PERCENT:3014buffer.append(symbols.getPercentText());3015continue;3016case PATTERN_PER_MILLE:3017buffer.append(symbols.getPerMillText());3018continue;3019case PATTERN_MINUS:3020buffer.append(symbols.getMinusSignText());3021continue;3022}3023}3024buffer.append(c);3025}3026return buffer.toString();3027}30283029/**3030* Expand an affix pattern into an array of FieldPositions describing3031* how the pattern would be expanded.3032* All characters in the3033* pattern are literal unless prefixed by QUOTE. The following characters3034* after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,3035* PATTERN_MINUS, and CURRENCY_SIGN. If CURRENCY_SIGN is doubled (QUOTE +3036* CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 42173037* currency code. Any other character after a QUOTE represents itself.3038* QUOTE must be followed by another character; QUOTE may not occur by3039* itself at the end of the pattern.3040*3041* @param pattern the non-null, possibly empty pattern3042* @return FieldPosition array of the resulting fields.3043*/3044private FieldPosition[] expandAffix(String pattern) {3045ArrayList<FieldPosition> positions = null;3046int stringIndex = 0;3047for (int i=0; i<pattern.length(); ) {3048char c = pattern.charAt(i++);3049if (c == QUOTE) {3050Format.Field fieldID = null;3051String string = null;3052c = pattern.charAt(i++);3053switch (c) {3054case CURRENCY_SIGN:3055if (i<pattern.length() &&3056pattern.charAt(i) == CURRENCY_SIGN) {3057++i;3058string = symbols.getInternationalCurrencySymbol();3059} else {3060string = symbols.getCurrencySymbol();3061}3062fieldID = Field.CURRENCY;3063break;3064case PATTERN_PERCENT:3065string = symbols.getPercentText();3066fieldID = Field.PERCENT;3067break;3068case PATTERN_PER_MILLE:3069string = symbols.getPerMillText();3070fieldID = Field.PERMILLE;3071break;3072case PATTERN_MINUS:3073string = symbols.getMinusSignText();3074fieldID = Field.SIGN;3075break;3076}30773078if (fieldID != null && !string.isEmpty()) {3079if (positions == null) {3080positions = new ArrayList<>(2);3081}3082FieldPosition fp = new FieldPosition(fieldID);3083fp.setBeginIndex(stringIndex);3084fp.setEndIndex(stringIndex + string.length());3085positions.add(fp);3086stringIndex += string.length();3087continue;3088}3089}3090stringIndex++;3091}3092if (positions != null) {3093return positions.toArray(EmptyFieldPositionArray);3094}3095return EmptyFieldPositionArray;3096}30973098/**3099* Appends an affix pattern to the given StringBuffer, quoting special3100* characters as needed. Uses the internal affix pattern, if that exists,3101* or the literal affix, if the internal affix pattern is null. The3102* appended string will generate the same affix pattern (or literal affix)3103* when passed to toPattern().3104*3105* @param buffer the affix string is appended to this3106* @param affixPattern a pattern such as posPrefixPattern; may be null3107* @param expAffix a corresponding expanded affix, such as positivePrefix.3108* Ignored unless affixPattern is null. If affixPattern is null, then3109* expAffix is appended as a literal affix.3110* @param localized true if the appended pattern should contain localized3111* pattern characters; otherwise, non-localized pattern chars are appended3112*/3113private void appendAffix(StringBuffer buffer, String affixPattern,3114String expAffix, boolean localized) {3115if (affixPattern == null) {3116appendAffix(buffer, expAffix, localized);3117} else {3118int i;3119for (int pos=0; pos<affixPattern.length(); pos=i) {3120i = affixPattern.indexOf(QUOTE, pos);3121if (i < 0) {3122appendAffix(buffer, affixPattern.substring(pos), localized);3123break;3124}3125if (i > pos) {3126appendAffix(buffer, affixPattern.substring(pos, i), localized);3127}3128char c = affixPattern.charAt(++i);3129++i;3130if (c == QUOTE) {3131buffer.append(c);3132// Fall through and append another QUOTE below3133} else if (c == CURRENCY_SIGN &&3134i<affixPattern.length() &&3135affixPattern.charAt(i) == CURRENCY_SIGN) {3136++i;3137buffer.append(c);3138// Fall through and append another CURRENCY_SIGN below3139} else if (localized) {3140switch (c) {3141case PATTERN_PERCENT:3142buffer.append(symbols.getPercentText());3143continue;3144case PATTERN_PER_MILLE:3145buffer.append(symbols.getPerMillText());3146continue;3147case PATTERN_MINUS:3148buffer.append(symbols.getMinusSignText());3149continue;3150}3151}3152buffer.append(c);3153}3154}3155}31563157/**3158* Append an affix to the given StringBuffer, using quotes if3159* there are special characters. Single quotes themselves must be3160* escaped in either case.3161*/3162private void appendAffix(StringBuffer buffer, String affix, boolean localized) {3163boolean needQuote;3164if (localized) {3165needQuote = affix.indexOf(symbols.getZeroDigit()) >= 03166|| affix.indexOf(symbols.getGroupingSeparator()) >= 03167|| affix.indexOf(symbols.getDecimalSeparator()) >= 03168|| affix.indexOf(symbols.getPercentText()) >= 03169|| affix.indexOf(symbols.getPerMillText()) >= 03170|| affix.indexOf(symbols.getDigit()) >= 03171|| affix.indexOf(symbols.getPatternSeparator()) >= 03172|| affix.indexOf(symbols.getMinusSignText()) >= 03173|| affix.indexOf(CURRENCY_SIGN) >= 0;3174} else {3175needQuote = affix.indexOf(PATTERN_ZERO_DIGIT) >= 03176|| affix.indexOf(PATTERN_GROUPING_SEPARATOR) >= 03177|| affix.indexOf(PATTERN_DECIMAL_SEPARATOR) >= 03178|| affix.indexOf(PATTERN_PERCENT) >= 03179|| affix.indexOf(PATTERN_PER_MILLE) >= 03180|| affix.indexOf(PATTERN_DIGIT) >= 03181|| affix.indexOf(PATTERN_SEPARATOR) >= 03182|| affix.indexOf(PATTERN_MINUS) >= 03183|| affix.indexOf(CURRENCY_SIGN) >= 0;3184}3185if (needQuote) buffer.append('\'');3186if (affix.indexOf('\'') < 0) buffer.append(affix);3187else {3188for (int j=0; j<affix.length(); ++j) {3189char c = affix.charAt(j);3190buffer.append(c);3191if (c == '\'') buffer.append(c);3192}3193}3194if (needQuote) buffer.append('\'');3195}31963197/**3198* Does the real work of generating a pattern. */3199private String toPattern(boolean localized) {3200StringBuffer result = new StringBuffer();3201for (int j = 1; j >= 0; --j) {3202if (j == 1)3203appendAffix(result, posPrefixPattern, positivePrefix, localized);3204else appendAffix(result, negPrefixPattern, negativePrefix, localized);3205int i;3206int digitCount = useExponentialNotation3207? getMaximumIntegerDigits()3208: Math.max(groupingSize, getMinimumIntegerDigits())+1;3209for (i = digitCount; i > 0; --i) {3210if (i != digitCount && isGroupingUsed() && groupingSize != 0 &&3211i % groupingSize == 0) {3212result.append(localized ? symbols.getGroupingSeparator() :3213PATTERN_GROUPING_SEPARATOR);3214}3215result.append(i <= getMinimumIntegerDigits()3216? (localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT)3217: (localized ? symbols.getDigit() : PATTERN_DIGIT));3218}3219if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown)3220result.append(localized ? symbols.getDecimalSeparator() :3221PATTERN_DECIMAL_SEPARATOR);3222for (i = 0; i < getMaximumFractionDigits(); ++i) {3223if (i < getMinimumFractionDigits()) {3224result.append(localized ? symbols.getZeroDigit() :3225PATTERN_ZERO_DIGIT);3226} else {3227result.append(localized ? symbols.getDigit() :3228PATTERN_DIGIT);3229}3230}3231if (useExponentialNotation)3232{3233result.append(localized ? symbols.getExponentSeparator() :3234PATTERN_EXPONENT);3235for (i=0; i<minExponentDigits; ++i)3236result.append(localized ? symbols.getZeroDigit() :3237PATTERN_ZERO_DIGIT);3238}3239if (j == 1) {3240appendAffix(result, posSuffixPattern, positiveSuffix, localized);3241if ((negSuffixPattern == posSuffixPattern && // n == p == null3242negativeSuffix.equals(positiveSuffix))3243|| (negSuffixPattern != null &&3244negSuffixPattern.equals(posSuffixPattern))) {3245if ((negPrefixPattern != null && posPrefixPattern != null &&3246negPrefixPattern.equals("'-" + posPrefixPattern)) ||3247(negPrefixPattern == posPrefixPattern && // n == p == null3248negativePrefix.equals(symbols.getMinusSignText() + positivePrefix)))3249break;3250}3251result.append(localized ? symbols.getPatternSeparator() :3252PATTERN_SEPARATOR);3253} else appendAffix(result, negSuffixPattern, negativeSuffix, localized);3254}3255return result.toString();3256}32573258/**3259* Apply the given pattern to this Format object. A pattern is a3260* short-hand specification for the various formatting properties.3261* These properties can also be changed individually through the3262* various setter methods.3263* <p>3264* There is no limit to integer digits set3265* by this routine, since that is the typical end-user desire;3266* use setMaximumInteger if you want to set a real value.3267* For negative numbers, use a second pattern, separated by a semicolon3268* <P>Example {@code "#,#00.0#"} → 1,234.563269* <P>This means a minimum of 2 integer digits, 1 fraction digit, and3270* a maximum of 2 fraction digits.3271* <p>Example: {@code "#,#00.0#;(#,#00.0#)"} for negatives in3272* parentheses.3273* <p>In negative patterns, the minimum and maximum counts are ignored;3274* these are presumed to be set in the positive pattern.3275*3276* @param pattern a new pattern3277* @throws NullPointerException if {@code pattern} is null3278* @throws IllegalArgumentException if the given pattern is invalid.3279*/3280public void applyPattern(String pattern) {3281applyPattern(pattern, false);3282}32833284/**3285* Apply the given pattern to this Format object. The pattern3286* is assumed to be in a localized notation. A pattern is a3287* short-hand specification for the various formatting properties.3288* These properties can also be changed individually through the3289* various setter methods.3290* <p>3291* There is no limit to integer digits set3292* by this routine, since that is the typical end-user desire;3293* use setMaximumInteger if you want to set a real value.3294* For negative numbers, use a second pattern, separated by a semicolon3295* <P>Example {@code "#,#00.0#"} → 1,234.563296* <P>This means a minimum of 2 integer digits, 1 fraction digit, and3297* a maximum of 2 fraction digits.3298* <p>Example: {@code "#,#00.0#;(#,#00.0#)"} for negatives in3299* parentheses.3300* <p>In negative patterns, the minimum and maximum counts are ignored;3301* these are presumed to be set in the positive pattern.3302*3303* @param pattern a new pattern3304* @throws NullPointerException if {@code pattern} is null3305* @throws IllegalArgumentException if the given pattern is invalid.3306*/3307public void applyLocalizedPattern(String pattern) {3308applyPattern(pattern, true);3309}33103311/**3312* Does the real work of applying a pattern.3313*/3314private void applyPattern(String pattern, boolean localized) {3315char zeroDigit = PATTERN_ZERO_DIGIT;3316char groupingSeparator = PATTERN_GROUPING_SEPARATOR;3317char decimalSeparator = PATTERN_DECIMAL_SEPARATOR;3318char percent = PATTERN_PERCENT;3319char perMill = PATTERN_PER_MILLE;3320char digit = PATTERN_DIGIT;3321char separator = PATTERN_SEPARATOR;3322String exponent = PATTERN_EXPONENT;3323char minus = PATTERN_MINUS;3324if (localized) {3325zeroDigit = symbols.getZeroDigit();3326groupingSeparator = symbols.getGroupingSeparator();3327decimalSeparator = symbols.getDecimalSeparator();3328percent = symbols.getPercent();3329perMill = symbols.getPerMill();3330digit = symbols.getDigit();3331separator = symbols.getPatternSeparator();3332exponent = symbols.getExponentSeparator();3333minus = symbols.getMinusSign();3334}3335boolean gotNegative = false;3336decimalSeparatorAlwaysShown = false;3337isCurrencyFormat = false;3338useExponentialNotation = false;33393340int start = 0;3341for (int j = 1; j >= 0 && start < pattern.length(); --j) {3342boolean inQuote = false;3343StringBuffer prefix = new StringBuffer();3344StringBuffer suffix = new StringBuffer();3345int decimalPos = -1;3346int multiplier = 1;3347int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0;3348byte groupingCount = -1;33493350// The phase ranges from 0 to 2. Phase 0 is the prefix. Phase 1 is3351// the section of the pattern with digits, decimal separator,3352// grouping characters. Phase 2 is the suffix. In phases 0 and 2,3353// percent, per mille, and currency symbols are recognized and3354// translated. The separation of the characters into phases is3355// strictly enforced; if phase 1 characters are to appear in the3356// suffix, for example, they must be quoted.3357int phase = 0;33583359// The affix is either the prefix or the suffix.3360StringBuffer affix = prefix;33613362for (int pos = start; pos < pattern.length(); ++pos) {3363char ch = pattern.charAt(pos);3364switch (phase) {3365case 0:3366case 2:3367// Process the prefix / suffix characters3368if (inQuote) {3369// A quote within quotes indicates either the closing3370// quote or two quotes, which is a quote literal. That3371// is, we have the second quote in 'do' or 'don''t'.3372if (ch == QUOTE) {3373if ((pos+1) < pattern.length() &&3374pattern.charAt(pos+1) == QUOTE) {3375++pos;3376affix.append("''"); // 'don''t'3377} else {3378inQuote = false; // 'do'3379}3380continue;3381}3382} else {3383// Process unquoted characters seen in prefix or suffix3384// phase.3385if (ch == digit ||3386ch == zeroDigit ||3387ch == groupingSeparator ||3388ch == decimalSeparator) {3389phase = 1;3390--pos; // Reprocess this character3391continue;3392} else if (ch == CURRENCY_SIGN) {3393// Use lookahead to determine if the currency sign3394// is doubled or not.3395boolean doubled = (pos + 1) < pattern.length() &&3396pattern.charAt(pos + 1) == CURRENCY_SIGN;3397if (doubled) { // Skip over the doubled character3398++pos;3399}3400isCurrencyFormat = true;3401affix.append(doubled ? "'\u00A4\u00A4" : "'\u00A4");3402continue;3403} else if (ch == QUOTE) {3404// A quote outside quotes indicates either the3405// opening quote or two quotes, which is a quote3406// literal. That is, we have the first quote in 'do'3407// or o''clock.3408if (ch == QUOTE) {3409if ((pos+1) < pattern.length() &&3410pattern.charAt(pos+1) == QUOTE) {3411++pos;3412affix.append("''"); // o''clock3413} else {3414inQuote = true; // 'do'3415}3416continue;3417}3418} else if (ch == separator) {3419// Don't allow separators before we see digit3420// characters of phase 1, and don't allow separators3421// in the second pattern (j == 0).3422if (phase == 0 || j == 0) {3423throw new IllegalArgumentException("Unquoted special character '" +3424ch + "' in pattern \"" + pattern + '"');3425}3426start = pos + 1;3427pos = pattern.length();3428continue;3429}34303431// Next handle characters which are appended directly.3432else if (ch == percent) {3433if (multiplier != 1) {3434throw new IllegalArgumentException("Too many percent/per mille characters in pattern \"" +3435pattern + '"');3436}3437multiplier = 100;3438affix.append("'%");3439continue;3440} else if (ch == perMill) {3441if (multiplier != 1) {3442throw new IllegalArgumentException("Too many percent/per mille characters in pattern \"" +3443pattern + '"');3444}3445multiplier = 1000;3446affix.append("'\u2030");3447continue;3448} else if (ch == minus) {3449affix.append("'-");3450continue;3451}3452}3453// Note that if we are within quotes, or if this is an3454// unquoted, non-special character, then we usually fall3455// through to here.3456affix.append(ch);3457break;34583459case 1:3460// The negative subpattern (j = 0) serves only to specify the3461// negative prefix and suffix, so all the phase 1 characters3462// e.g. digits, zeroDigit, groupingSeparator,3463// decimalSeparator, exponent are ignored3464if (j == 0) {3465while (pos < pattern.length()) {3466char negPatternChar = pattern.charAt(pos);3467if (negPatternChar == digit3468|| negPatternChar == zeroDigit3469|| negPatternChar == groupingSeparator3470|| negPatternChar == decimalSeparator) {3471++pos;3472} else if (pattern.regionMatches(pos, exponent,34730, exponent.length())) {3474pos = pos + exponent.length();3475} else {3476// Not a phase 1 character, consider it as3477// suffix and parse it in phase 23478--pos; //process it again in outer loop3479phase = 2;3480affix = suffix;3481break;3482}3483}3484continue;3485}34863487// Process the digits, decimal, and grouping characters. We3488// record five pieces of information. We expect the digits3489// to occur in the pattern ####0000.####, and we record the3490// number of left digits, zero (central) digits, and right3491// digits. The position of the last grouping character is3492// recorded (should be somewhere within the first two blocks3493// of characters), as is the position of the decimal point,3494// if any (should be in the zero digits). If there is no3495// decimal point, then there should be no right digits.3496if (ch == digit) {3497if (zeroDigitCount > 0) {3498++digitRightCount;3499} else {3500++digitLeftCount;3501}3502if (groupingCount >= 0 && decimalPos < 0) {3503++groupingCount;3504}3505} else if (ch == zeroDigit) {3506if (digitRightCount > 0) {3507throw new IllegalArgumentException("Unexpected '0' in pattern \"" +3508pattern + '"');3509}3510++zeroDigitCount;3511if (groupingCount >= 0 && decimalPos < 0) {3512++groupingCount;3513}3514} else if (ch == groupingSeparator) {3515groupingCount = 0;3516} else if (ch == decimalSeparator) {3517if (decimalPos >= 0) {3518throw new IllegalArgumentException("Multiple decimal separators in pattern \"" +3519pattern + '"');3520}3521decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;3522} else if (pattern.regionMatches(pos, exponent, 0, exponent.length())){3523if (useExponentialNotation) {3524throw new IllegalArgumentException("Multiple exponential " +3525"symbols in pattern \"" + pattern + '"');3526}3527useExponentialNotation = true;3528minExponentDigits = 0;35293530// Use lookahead to parse out the exponential part3531// of the pattern, then jump into phase 2.3532pos = pos+exponent.length();3533while (pos < pattern.length() &&3534pattern.charAt(pos) == zeroDigit) {3535++minExponentDigits;3536++pos;3537}35383539if ((digitLeftCount + zeroDigitCount) < 1 ||3540minExponentDigits < 1) {3541throw new IllegalArgumentException("Malformed exponential " +3542"pattern \"" + pattern + '"');3543}35443545// Transition to phase 23546phase = 2;3547affix = suffix;3548--pos;3549continue;3550} else {3551phase = 2;3552affix = suffix;3553--pos;3554continue;3555}3556break;3557}3558}35593560// Handle patterns with no '0' pattern character. These patterns3561// are legal, but must be interpreted. "##.###" -> "#0.###".3562// ".###" -> ".0##".3563/* We allow patterns of the form "####" to produce a zeroDigitCount3564* of zero (got that?); although this seems like it might make it3565* possible for format() to produce empty strings, format() checks3566* for this condition and outputs a zero digit in this situation.3567* Having a zeroDigitCount of zero yields a minimum integer digits3568* of zero, which allows proper round-trip patterns. That is, we3569* don't want "#" to become "#0" when toPattern() is called (even3570* though that's what it really is, semantically).3571*/3572if (zeroDigitCount == 0 && digitLeftCount > 0 && decimalPos >= 0) {3573// Handle "###.###" and "###." and ".###"3574int n = decimalPos;3575if (n == 0) { // Handle ".###"3576++n;3577}3578digitRightCount = digitLeftCount - n;3579digitLeftCount = n - 1;3580zeroDigitCount = 1;3581}35823583// Do syntax checking on the digits.3584if ((decimalPos < 0 && digitRightCount > 0) ||3585(decimalPos >= 0 && (decimalPos < digitLeftCount ||3586decimalPos > (digitLeftCount + zeroDigitCount))) ||3587groupingCount == 0 || inQuote) {3588throw new IllegalArgumentException("Malformed pattern \"" +3589pattern + '"');3590}35913592if (j == 1) {3593posPrefixPattern = prefix.toString();3594posSuffixPattern = suffix.toString();3595negPrefixPattern = posPrefixPattern; // assume these for now3596negSuffixPattern = posSuffixPattern;3597int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;3598/* The effectiveDecimalPos is the position the decimal is at or3599* would be at if there is no decimal. Note that if decimalPos<0,3600* then digitTotalCount == digitLeftCount + zeroDigitCount.3601*/3602int effectiveDecimalPos = decimalPos >= 0 ?3603decimalPos : digitTotalCount;3604setMinimumIntegerDigits(effectiveDecimalPos - digitLeftCount);3605setMaximumIntegerDigits(useExponentialNotation ?3606digitLeftCount + getMinimumIntegerDigits() :3607MAXIMUM_INTEGER_DIGITS);3608setMaximumFractionDigits(decimalPos >= 0 ?3609(digitTotalCount - decimalPos) : 0);3610setMinimumFractionDigits(decimalPos >= 0 ?3611(digitLeftCount + zeroDigitCount - decimalPos) : 0);3612setGroupingUsed(groupingCount > 0);3613this.groupingSize = (groupingCount > 0) ? groupingCount : 0;3614this.multiplier = multiplier;3615setDecimalSeparatorAlwaysShown(decimalPos == 0 ||3616decimalPos == digitTotalCount);3617} else {3618negPrefixPattern = prefix.toString();3619negSuffixPattern = suffix.toString();3620gotNegative = true;3621}3622}36233624if (pattern.isEmpty()) {3625posPrefixPattern = posSuffixPattern = "";3626setMinimumIntegerDigits(0);3627setMaximumIntegerDigits(MAXIMUM_INTEGER_DIGITS);3628setMinimumFractionDigits(0);3629setMaximumFractionDigits(MAXIMUM_FRACTION_DIGITS);3630}36313632// If there was no negative pattern, or if the negative pattern is3633// identical to the positive pattern, then prepend the minus sign to3634// the positive pattern to form the negative pattern.3635if (!gotNegative ||3636(negPrefixPattern.equals(posPrefixPattern)3637&& negSuffixPattern.equals(posSuffixPattern))) {3638negSuffixPattern = posSuffixPattern;3639negPrefixPattern = "'-" + posPrefixPattern;3640}36413642expandAffixes();3643}36443645/**3646* Sets the maximum number of digits allowed in the integer portion of a3647* number.3648* For formatting numbers other than {@code BigInteger} and3649* {@code BigDecimal} objects, the lower of {@code newValue} and3650* 309 is used. Negative input values are replaced with 0.3651* @see NumberFormat#setMaximumIntegerDigits3652*/3653@Override3654public void setMaximumIntegerDigits(int newValue) {3655maximumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS);3656super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?3657DOUBLE_INTEGER_DIGITS : maximumIntegerDigits);3658if (minimumIntegerDigits > maximumIntegerDigits) {3659minimumIntegerDigits = maximumIntegerDigits;3660super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?3661DOUBLE_INTEGER_DIGITS : minimumIntegerDigits);3662}3663fastPathCheckNeeded = true;3664}36653666/**3667* Sets the minimum number of digits allowed in the integer portion of a3668* number.3669* For formatting numbers other than {@code BigInteger} and3670* {@code BigDecimal} objects, the lower of {@code newValue} and3671* 309 is used. Negative input values are replaced with 0.3672* @see NumberFormat#setMinimumIntegerDigits3673*/3674@Override3675public void setMinimumIntegerDigits(int newValue) {3676minimumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS);3677super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?3678DOUBLE_INTEGER_DIGITS : minimumIntegerDigits);3679if (minimumIntegerDigits > maximumIntegerDigits) {3680maximumIntegerDigits = minimumIntegerDigits;3681super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?3682DOUBLE_INTEGER_DIGITS : maximumIntegerDigits);3683}3684fastPathCheckNeeded = true;3685}36863687/**3688* Sets the maximum number of digits allowed in the fraction portion of a3689* number.3690* For formatting numbers other than {@code BigInteger} and3691* {@code BigDecimal} objects, the lower of {@code newValue} and3692* 340 is used. Negative input values are replaced with 0.3693* @see NumberFormat#setMaximumFractionDigits3694*/3695@Override3696public void setMaximumFractionDigits(int newValue) {3697maximumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS);3698super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ?3699DOUBLE_FRACTION_DIGITS : maximumFractionDigits);3700if (minimumFractionDigits > maximumFractionDigits) {3701minimumFractionDigits = maximumFractionDigits;3702super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ?3703DOUBLE_FRACTION_DIGITS : minimumFractionDigits);3704}3705fastPathCheckNeeded = true;3706}37073708/**3709* Sets the minimum number of digits allowed in the fraction portion of a3710* number.3711* For formatting numbers other than {@code BigInteger} and3712* {@code BigDecimal} objects, the lower of {@code newValue} and3713* 340 is used. Negative input values are replaced with 0.3714* @see NumberFormat#setMinimumFractionDigits3715*/3716@Override3717public void setMinimumFractionDigits(int newValue) {3718minimumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS);3719super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ?3720DOUBLE_FRACTION_DIGITS : minimumFractionDigits);3721if (minimumFractionDigits > maximumFractionDigits) {3722maximumFractionDigits = minimumFractionDigits;3723super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ?3724DOUBLE_FRACTION_DIGITS : maximumFractionDigits);3725}3726fastPathCheckNeeded = true;3727}37283729/**3730* Gets the maximum number of digits allowed in the integer portion of a3731* number.3732* For formatting numbers other than {@code BigInteger} and3733* {@code BigDecimal} objects, the lower of the return value and3734* 309 is used.3735* @see #setMaximumIntegerDigits3736*/3737@Override3738public int getMaximumIntegerDigits() {3739return maximumIntegerDigits;3740}37413742/**3743* Gets the minimum number of digits allowed in the integer portion of a3744* number.3745* For formatting numbers other than {@code BigInteger} and3746* {@code BigDecimal} objects, the lower of the return value and3747* 309 is used.3748* @see #setMinimumIntegerDigits3749*/3750@Override3751public int getMinimumIntegerDigits() {3752return minimumIntegerDigits;3753}37543755/**3756* Gets the maximum number of digits allowed in the fraction portion of a3757* number.3758* For formatting numbers other than {@code BigInteger} and3759* {@code BigDecimal} objects, the lower of the return value and3760* 340 is used.3761* @see #setMaximumFractionDigits3762*/3763@Override3764public int getMaximumFractionDigits() {3765return maximumFractionDigits;3766}37673768/**3769* Gets the minimum number of digits allowed in the fraction portion of a3770* number.3771* For formatting numbers other than {@code BigInteger} and3772* {@code BigDecimal} objects, the lower of the return value and3773* 340 is used.3774* @see #setMinimumFractionDigits3775*/3776@Override3777public int getMinimumFractionDigits() {3778return minimumFractionDigits;3779}37803781/**3782* Gets the currency used by this decimal format when formatting3783* currency values.3784* The currency is obtained by calling3785* {@link DecimalFormatSymbols#getCurrency DecimalFormatSymbols.getCurrency}3786* on this number format's symbols.3787*3788* @return the currency used by this decimal format, or {@code null}3789* @since 1.43790*/3791@Override3792public Currency getCurrency() {3793return symbols.getCurrency();3794}37953796/**3797* Sets the currency used by this number format when formatting3798* currency values. This does not update the minimum or maximum3799* number of fraction digits used by the number format.3800* The currency is set by calling3801* {@link DecimalFormatSymbols#setCurrency DecimalFormatSymbols.setCurrency}3802* on this number format's symbols.3803*3804* @param currency the new currency to be used by this decimal format3805* @throws NullPointerException if {@code currency} is null3806* @since 1.43807*/3808@Override3809public void setCurrency(Currency currency) {3810if (currency != symbols.getCurrency()) {3811symbols.setCurrency(currency);3812if (isCurrencyFormat) {3813expandAffixes();3814}3815}3816fastPathCheckNeeded = true;3817}38183819/**3820* Gets the {@link java.math.RoundingMode} used in this DecimalFormat.3821*3822* @return The {@code RoundingMode} used for this DecimalFormat.3823* @see #setRoundingMode(RoundingMode)3824* @since 1.63825*/3826@Override3827public RoundingMode getRoundingMode() {3828return roundingMode;3829}38303831/**3832* Sets the {@link java.math.RoundingMode} used in this DecimalFormat.3833*3834* @param roundingMode The {@code RoundingMode} to be used3835* @see #getRoundingMode()3836* @throws NullPointerException if {@code roundingMode} is null.3837* @since 1.63838*/3839@Override3840public void setRoundingMode(RoundingMode roundingMode) {3841if (roundingMode == null) {3842throw new NullPointerException();3843}38443845this.roundingMode = roundingMode;3846digitList.setRoundingMode(roundingMode);3847fastPathCheckNeeded = true;3848}38493850/**3851* Reads the default serializable fields from the stream and performs3852* validations and adjustments for older serialized versions. The3853* validations and adjustments are:3854* <ol>3855* <li>3856* Verify that the superclass's digit count fields correctly reflect3857* the limits imposed on formatting numbers other than3858* {@code BigInteger} and {@code BigDecimal} objects. These3859* limits are stored in the superclass for serialization compatibility3860* with older versions, while the limits for {@code BigInteger} and3861* {@code BigDecimal} objects are kept in this class.3862* If, in the superclass, the minimum or maximum integer digit count is3863* larger than {@code DOUBLE_INTEGER_DIGITS} or if the minimum or3864* maximum fraction digit count is larger than3865* {@code DOUBLE_FRACTION_DIGITS}, then the stream data is invalid3866* and this method throws an {@code InvalidObjectException}.3867* <li>3868* If {@code serialVersionOnStream} is less than 4, initialize3869* {@code roundingMode} to {@link java.math.RoundingMode#HALF_EVEN3870* RoundingMode.HALF_EVEN}. This field is new with version 4.3871* <li>3872* If {@code serialVersionOnStream} is less than 3, then call3873* the setters for the minimum and maximum integer and fraction digits with3874* the values of the corresponding superclass getters to initialize the3875* fields in this class. The fields in this class are new with version 3.3876* <li>3877* If {@code serialVersionOnStream} is less than 1, indicating that3878* the stream was written by JDK 1.1, initialize3879* {@code useExponentialNotation}3880* to false, since it was not present in JDK 1.1.3881* <li>3882* Set {@code serialVersionOnStream} to the maximum allowed value so3883* that default serialization will work properly if this object is streamed3884* out again.3885* </ol>3886*3887* <p>Stream versions older than 2 will not have the affix pattern variables3888* {@code posPrefixPattern} etc. As a result, they will be initialized3889* to {@code null}, which means the affix strings will be taken as3890* literal values. This is exactly what we want, since that corresponds to3891* the pre-version-2 behavior.3892*/3893@java.io.Serial3894private void readObject(ObjectInputStream stream)3895throws IOException, ClassNotFoundException3896{3897stream.defaultReadObject();3898digitList = new DigitList();38993900// We force complete fast-path reinitialization when the instance is3901// deserialized. See clone() comment on fastPathCheckNeeded.3902fastPathCheckNeeded = true;3903isFastPath = false;3904fastPathData = null;39053906if (serialVersionOnStream < 4) {3907setRoundingMode(RoundingMode.HALF_EVEN);3908} else {3909setRoundingMode(getRoundingMode());3910}39113912// We only need to check the maximum counts because NumberFormat3913// .readObject has already ensured that the maximum is greater than the3914// minimum count.3915if (super.getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||3916super.getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {3917throw new InvalidObjectException("Digit count out of range");3918}3919if (serialVersionOnStream < 3) {3920setMaximumIntegerDigits(super.getMaximumIntegerDigits());3921setMinimumIntegerDigits(super.getMinimumIntegerDigits());3922setMaximumFractionDigits(super.getMaximumFractionDigits());3923setMinimumFractionDigits(super.getMinimumFractionDigits());3924}3925if (serialVersionOnStream < 1) {3926// Didn't have exponential fields3927useExponentialNotation = false;3928}39293930// Restore the invariant value if groupingSize is invalid.3931if (groupingSize < 0) {3932groupingSize = 3;3933}39343935serialVersionOnStream = currentSerialVersion;3936}39373938//----------------------------------------------------------------------3939// INSTANCE VARIABLES3940//----------------------------------------------------------------------39413942private transient DigitList digitList = new DigitList();39433944/**3945* The symbol used as a prefix when formatting positive numbers, e.g. "+".3946*3947* @serial3948* @see #getPositivePrefix3949*/3950private String positivePrefix = "";39513952/**3953* The symbol used as a suffix when formatting positive numbers.3954* This is often an empty string.3955*3956* @serial3957* @see #getPositiveSuffix3958*/3959private String positiveSuffix = "";39603961/**3962* The symbol used as a prefix when formatting negative numbers, e.g. "-".3963*3964* @serial3965* @see #getNegativePrefix3966*/3967private String negativePrefix = "-";39683969/**3970* The symbol used as a suffix when formatting negative numbers.3971* This is often an empty string.3972*3973* @serial3974* @see #getNegativeSuffix3975*/3976private String negativeSuffix = "";39773978/**3979* The prefix pattern for non-negative numbers. This variable corresponds3980* to {@code positivePrefix}.3981*3982* <p>This pattern is expanded by the method {@code expandAffix()} to3983* {@code positivePrefix} to update the latter to reflect changes in3984* {@code symbols}. If this variable is {@code null} then3985* {@code positivePrefix} is taken as a literal value that does not3986* change when {@code symbols} changes. This variable is always3987* {@code null} for {@code DecimalFormat} objects older than3988* stream version 2 restored from stream.3989*3990* @serial3991* @since 1.33992*/3993private String posPrefixPattern;39943995/**3996* The suffix pattern for non-negative numbers. This variable corresponds3997* to {@code positiveSuffix}. This variable is analogous to3998* {@code posPrefixPattern}; see that variable for further3999* documentation.4000*4001* @serial4002* @since 1.34003*/4004private String posSuffixPattern;40054006/**4007* The prefix pattern for negative numbers. This variable corresponds4008* to {@code negativePrefix}. This variable is analogous to4009* {@code posPrefixPattern}; see that variable for further4010* documentation.4011*4012* @serial4013* @since 1.34014*/4015private String negPrefixPattern;40164017/**4018* The suffix pattern for negative numbers. This variable corresponds4019* to {@code negativeSuffix}. This variable is analogous to4020* {@code posPrefixPattern}; see that variable for further4021* documentation.4022*4023* @serial4024* @since 1.34025*/4026private String negSuffixPattern;40274028/**4029* The multiplier for use in percent, per mille, etc.4030*4031* @serial4032* @see #getMultiplier4033*/4034private int multiplier = 1;40354036/**4037* The number of digits between grouping separators in the integer4038* portion of a number. Must be non-negative and less than or equal to4039* {@link java.lang.Byte#MAX_VALUE Byte.MAX_VALUE} if4040* {@code NumberFormat.groupingUsed} is true.4041*4042* @serial4043* @see #getGroupingSize4044* @see java.text.NumberFormat#isGroupingUsed4045*/4046private byte groupingSize = 3; // invariant, 0 - 127, if groupingUsed40474048/**4049* If true, forces the decimal separator to always appear in a formatted4050* number, even if the fractional part of the number is zero.4051*4052* @serial4053* @see #isDecimalSeparatorAlwaysShown4054*/4055private boolean decimalSeparatorAlwaysShown = false;40564057/**4058* If true, parse returns BigDecimal wherever possible.4059*4060* @serial4061* @see #isParseBigDecimal4062* @since 1.54063*/4064private boolean parseBigDecimal = false;406540664067/**4068* True if this object represents a currency format. This determines4069* whether the monetary decimal/grouping separators are used instead of the normal ones.4070*/4071private transient boolean isCurrencyFormat = false;40724073/**4074* The {@code DecimalFormatSymbols} object used by this format.4075* It contains the symbols used to format numbers, e.g. the grouping separator,4076* decimal separator, and so on.4077*4078* @serial4079* @see #setDecimalFormatSymbols4080* @see java.text.DecimalFormatSymbols4081*/4082private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();40834084/**4085* True to force the use of exponential (i.e. scientific) notation when formatting4086* numbers.4087*4088* @serial4089* @since 1.24090*/4091private boolean useExponentialNotation; // Newly persistent in the Java 2 platform v.1.240924093/**4094* FieldPositions describing the positive prefix String. This is4095* lazily created. Use {@code getPositivePrefixFieldPositions}4096* when needed.4097*/4098private transient FieldPosition[] positivePrefixFieldPositions;40994100/**4101* FieldPositions describing the positive suffix String. This is4102* lazily created. Use {@code getPositiveSuffixFieldPositions}4103* when needed.4104*/4105private transient FieldPosition[] positiveSuffixFieldPositions;41064107/**4108* FieldPositions describing the negative prefix String. This is4109* lazily created. Use {@code getNegativePrefixFieldPositions}4110* when needed.4111*/4112private transient FieldPosition[] negativePrefixFieldPositions;41134114/**4115* FieldPositions describing the negative suffix String. This is4116* lazily created. Use {@code getNegativeSuffixFieldPositions}4117* when needed.4118*/4119private transient FieldPosition[] negativeSuffixFieldPositions;41204121/**4122* The minimum number of digits used to display the exponent when a number is4123* formatted in exponential notation. This field is ignored if4124* {@code useExponentialNotation} is not true.4125*4126* @serial4127* @since 1.24128*/4129private byte minExponentDigits; // Newly persistent in the Java 2 platform v.1.241304131/**4132* The maximum number of digits allowed in the integer portion of a4133* {@code BigInteger} or {@code BigDecimal} number.4134* {@code maximumIntegerDigits} must be greater than or equal to4135* {@code minimumIntegerDigits}.4136*4137* @serial4138* @see #getMaximumIntegerDigits4139* @since 1.54140*/4141private int maximumIntegerDigits = super.getMaximumIntegerDigits();41424143/**4144* The minimum number of digits allowed in the integer portion of a4145* {@code BigInteger} or {@code BigDecimal} number.4146* {@code minimumIntegerDigits} must be less than or equal to4147* {@code maximumIntegerDigits}.4148*4149* @serial4150* @see #getMinimumIntegerDigits4151* @since 1.54152*/4153private int minimumIntegerDigits = super.getMinimumIntegerDigits();41544155/**4156* The maximum number of digits allowed in the fractional portion of a4157* {@code BigInteger} or {@code BigDecimal} number.4158* {@code maximumFractionDigits} must be greater than or equal to4159* {@code minimumFractionDigits}.4160*4161* @serial4162* @see #getMaximumFractionDigits4163* @since 1.54164*/4165private int maximumFractionDigits = super.getMaximumFractionDigits();41664167/**4168* The minimum number of digits allowed in the fractional portion of a4169* {@code BigInteger} or {@code BigDecimal} number.4170* {@code minimumFractionDigits} must be less than or equal to4171* {@code maximumFractionDigits}.4172*4173* @serial4174* @see #getMinimumFractionDigits4175* @since 1.54176*/4177private int minimumFractionDigits = super.getMinimumFractionDigits();41784179/**4180* The {@link java.math.RoundingMode} used in this DecimalFormat.4181*4182* @serial4183* @since 1.64184*/4185private RoundingMode roundingMode = RoundingMode.HALF_EVEN;41864187// ------ DecimalFormat fields for fast-path for double algorithm ------41884189/**4190* Helper inner utility class for storing the data used in the fast-path4191* algorithm. Almost all fields related to fast-path are encapsulated in4192* this class.4193*4194* Any {@code DecimalFormat} instance has a {@code fastPathData}4195* reference field that is null unless both the properties of the instance4196* are such that the instance is in the "fast-path" state, and a format call4197* has been done at least once while in this state.4198*4199* Almost all fields are related to the "fast-path" state only and don't4200* change until one of the instance properties is changed.4201*4202* {@code firstUsedIndex} and {@code lastFreeIndex} are the only4203* two fields that are used and modified while inside a call to4204* {@code fastDoubleFormat}.4205*4206*/4207private static class FastPathData {4208// --- Temporary fields used in fast-path, shared by several methods.42094210/** The first unused index at the end of the formatted result. */4211int lastFreeIndex;42124213/** The first used index at the beginning of the formatted result */4214int firstUsedIndex;42154216// --- State fields related to fast-path status. Changes due to a4217// property change only. Set by checkAndSetFastPathStatus() only.42184219/** Difference between locale zero and default zero representation. */4220int zeroDelta;42214222/** Locale char for grouping separator. */4223char groupingChar;42244225/** Fixed index position of last integral digit of formatted result */4226int integralLastIndex;42274228/** Fixed index position of first fractional digit of formatted result */4229int fractionalFirstIndex;42304231/** Fractional constants depending on decimal|currency state */4232double fractionalScaleFactor;4233int fractionalMaxIntBound;423442354236/** The char array buffer that will contain the formatted result */4237char[] fastPathContainer;42384239/** Suffixes recorded as char array for efficiency. */4240char[] charsPositivePrefix;4241char[] charsNegativePrefix;4242char[] charsPositiveSuffix;4243char[] charsNegativeSuffix;4244boolean positiveAffixesRequired = true;4245boolean negativeAffixesRequired = true;4246}42474248/** The format fast-path status of the instance. Logical state. */4249private transient boolean isFastPath = false;42504251/** Flag stating need of check and reinit fast-path status on next format call. */4252private transient boolean fastPathCheckNeeded = true;42534254/** DecimalFormat reference to its FastPathData */4255private transient FastPathData fastPathData;425642574258//----------------------------------------------------------------------42594260static final int currentSerialVersion = 4;42614262/**4263* The internal serial version which says which version was written.4264* Possible values are:4265* <ul>4266* <li><b>0</b> (default): versions before the Java 2 platform v1.24267* <li><b>1</b>: version for 1.2, which includes the two new fields4268* {@code useExponentialNotation} and4269* {@code minExponentDigits}.4270* <li><b>2</b>: version for 1.3 and later, which adds four new fields:4271* {@code posPrefixPattern}, {@code posSuffixPattern},4272* {@code negPrefixPattern}, and {@code negSuffixPattern}.4273* <li><b>3</b>: version for 1.5 and later, which adds five new fields:4274* {@code maximumIntegerDigits},4275* {@code minimumIntegerDigits},4276* {@code maximumFractionDigits},4277* {@code minimumFractionDigits}, and4278* {@code parseBigDecimal}.4279* <li><b>4</b>: version for 1.6 and later, which adds one new field:4280* {@code roundingMode}.4281* </ul>4282* @since 1.24283* @serial4284*/4285private int serialVersionOnStream = currentSerialVersion;42864287//----------------------------------------------------------------------4288// CONSTANTS4289//----------------------------------------------------------------------42904291// ------ Fast-Path for double Constants ------42924293/** Maximum valid integer value for applying fast-path algorithm */4294private static final double MAX_INT_AS_DOUBLE = (double) Integer.MAX_VALUE;42954296/**4297* The digit arrays used in the fast-path methods for collecting digits.4298* Using 3 constants arrays of chars ensures a very fast collection of digits4299*/4300private static class DigitArrays {4301static final char[] DigitOnes1000 = new char[1000];4302static final char[] DigitTens1000 = new char[1000];4303static final char[] DigitHundreds1000 = new char[1000];43044305// initialize on demand holder class idiom for arrays of digits4306static {4307int tenIndex = 0;4308int hundredIndex = 0;4309char digitOne = '0';4310char digitTen = '0';4311char digitHundred = '0';4312for (int i = 0; i < 1000; i++ ) {43134314DigitOnes1000[i] = digitOne;4315if (digitOne == '9')4316digitOne = '0';4317else4318digitOne++;43194320DigitTens1000[i] = digitTen;4321if (i == (tenIndex + 9)) {4322tenIndex += 10;4323if (digitTen == '9')4324digitTen = '0';4325else4326digitTen++;4327}43284329DigitHundreds1000[i] = digitHundred;4330if (i == (hundredIndex + 99)) {4331digitHundred++;4332hundredIndex += 100;4333}4334}4335}4336}4337// ------ Fast-Path for double Constants end ------43384339// Constants for characters used in programmatic (unlocalized) patterns.4340private static final char PATTERN_ZERO_DIGIT = '0';4341private static final char PATTERN_GROUPING_SEPARATOR = ',';4342private static final char PATTERN_DECIMAL_SEPARATOR = '.';4343private static final char PATTERN_PER_MILLE = '\u2030';4344private static final char PATTERN_PERCENT = '%';4345private static final char PATTERN_DIGIT = '#';4346private static final char PATTERN_SEPARATOR = ';';4347private static final String PATTERN_EXPONENT = "E";4348private static final char PATTERN_MINUS = '-';43494350/**4351* The CURRENCY_SIGN is the standard Unicode symbol for currency. It4352* is used in patterns and substituted with either the currency symbol,4353* or if it is doubled, with the international currency symbol. If the4354* CURRENCY_SIGN is seen in a pattern, then the decimal/grouping separators4355* are replaced with the monetary decimal/grouping separators.4356*4357* The CURRENCY_SIGN is not localized.4358*/4359private static final char CURRENCY_SIGN = '\u00A4';43604361private static final char QUOTE = '\'';43624363private static FieldPosition[] EmptyFieldPositionArray = new FieldPosition[0];43644365// Upper limit on integer and fraction digits for a Java double4366static final int DOUBLE_INTEGER_DIGITS = 309;4367static final int DOUBLE_FRACTION_DIGITS = 340;43684369// Upper limit on integer and fraction digits for BigDecimal and BigInteger4370static final int MAXIMUM_INTEGER_DIGITS = Integer.MAX_VALUE;4371static final int MAXIMUM_FRACTION_DIGITS = Integer.MAX_VALUE;43724373// Proclaim JDK 1.1 serial compatibility.4374@java.io.Serial4375static final long serialVersionUID = 864413376551465018L;4376}437743784379