DecimalFormat继承自NumberFormat,可以使用它将十进制的数以不同形式格式化为字符串形式,可以控制前导和尾随0、前缀、后缀、分组(千)、小数分隔符等,如果要更改格式符号(例如小数点分隔符)。

它有各种各样的设计使其能够解析和格式化数字的特征区域设置,包括对西方、阿拉伯和印度数字的支持。它也支持不同类型的数字,包括整数(123),定点数字(123.4),科学符号(1.23 e4),百分比(12%),以及货币金额(123美元)。所有这些都可以本地化。

可以将其DecimalFormatSymbolsDecimalFormat类一起使用。这些类在数字格式化方面提供了极大的灵活性,但它们可以代码更加复杂。

包:import java.text.DecimalFormat;

构建模式

  使用DecimalFormat模式指定格式设置String的模式属性pattern:

  1. DecimalFormat df = new DecimalFormat(pattern);

关于pattern,有:

数字格式模式语法

可以按照以下BNF(巴科斯范式)图表指定的规则为数字设计自己的格式模式:

  1. pattern subpattern {; subpattern}
  2. subpattern(子模式): {prefix} integer {.fraction(分数)} {suffix}
  3.  
  4. prefix(前缀):'\\ u0000'..'\\ uFFFD' - specialCharacters
  5. suffix(后缀):'\\ u0000'..'\\ uFFFD' - specialCharacters
  6. integer'#'*'0'*'0'
  7. 分数:  '0'*'#'*

上图中使用的符号如下表所示:

符号 描述
X* 0个或更多个X实例
(X | Y) X或Y
X..Y 从X到Y的任何字符,包括在内
S - T S中的字符,除了T中的字符
{X} X是可选的
  1. 模式中的特殊符号
符号  描述
0 一个数字
# 一个数字,0显示为缺省(即空字符) 
. 小数点
分组分隔符
E 指数表示的底数指数分隔符
分隔格式
- 负号前缀
% 乘以100并显示为百分比
乘以1000并显示为千分比
¤ 货币符号; 用货币符号代替; 如果加倍,用国际货币符号代替; 如果存在于模式中,则使用货币小数分隔符而不是小数分隔符
X 任何其他字符都可以在前缀或者后缀中使用
用于引号前缀或后缀中的特殊符号

示例:

DecimalFormatDemo程序输出
value pattern output 说明
123456.789 ###,###。### 123,456.789 井号(#)表示一个数字,逗号是分组分隔符的占位符,句点是小数分隔符的占位符。
123456.789 ###。## 123456.79 value有三个数字的小数点右边,但pattern只有两个。该format方法通过四舍五入来处理这个问题。
123.78 000000.000 000123.780 pattern指定前导和尾随零,因为0字符被用来代替井号(#)。
12345.67 $ ###,###。### $ 12,345.67 pattern美元符号($)中的第一个字符。请注意,它紧接在格式化的最左边的数字之前output
12345.67 \ u00A5 ###,###。### ¥12,345.67 pattern与Unicode值00A5指定为日元(¥)货币符号。
  1. DecimalFormat df = new DecimalFormat("000.###");
  2. String s = df.format( 1.11111);
  3. System.out.println(s);
  4. //output: 001.111
  5.  
  6. df.applyPattern("000.000"); //重新应用新的模式
  7. System.out.println(df.format(1.11111));
  8. //output: 001.111
  9.  
  10. df.applyPattern("000E000");
  11. System.out.println(df.format(1111111));
  12. //output: 111E004 (1111111 约等于111 X 10^4)
  13. df.applyPattern("0E0");
  14. System.out.println(df.format(1000000000));
  15. //output: 1E9
  16.  
  17. df.applyPattern("###,###,###.###");
  18. System.out.println(df.format(11111111.11));
  19. //output:11,111,111.11
  20.  
  21. df.applyPattern("0.0%");
  22. System.out.println(df.format(0.1));
  23. //output: 10.0%
  24.  
  25. df.applyPattern("sd.00"); //可添加其他常规字符
  26. System.out.println(df.format(0.1));
  27. //output: sd.10

区域敏感格式

前面的示例DecimalFormat为默认值创建了一个对象Locale。如果您想要一个DecimalFormat非默认对象Locale,则实例化a NumberFormat然后将其强制转换为DecimalFormat。这是一个例子:

  1. NumberFormat nf = NumberFormat.getNumberInstanceloc);
  2. DecimalFormat df =(DecimalFormatnf;
  3. df.applyPattern(图案);
  4. String output = df.formatvalue);
  5. System.out.printlnpattern +“”+ output +“”+ loc.toString());

运行上一个代码示例将导致后面的输出。格式化的数字位于第二列,具体取决于Locale

  1. ###,###。### 123,456.789 zh_CN
  2. ###,###。### 123.456,789 de_DE
  3. ###,###。### 123 456,789 fr_FR

到目前为止,这里讨论的格式模式遵循美国英语的惯例。例如,在模式###,###。##中,逗号是千位分隔符,句点表示小数点。如果您的最终用户没有接触到它,那么这个约定很好。但是,某些应用程序(如电子表格和报表生成器)允许最终用户定义自己的格式设置模式。对于这些应用程序,最终用户指定的格式模式应使用本地化表示法。在这些情况下,您将要调用applyLocalizedPatternDecimalFormat对象上的方法。

改变格式符号

您可以使用 DecimalFormatSymbols类更改format方法生成的格式化数字中出现的符号。这些符号包括小数分隔符,分组分隔符,减号和百分号等。

下一个示例DecimalFormatSymbols通过将奇怪的格式应用于数字来演示该类。这种不寻常的格式是调用的结果setDecimalSeparatorsetGroupingSeparatorsetGroupingSize方法。

  1. DecimalFormatSymbols unusualSymbols = new DecimalFormatSymbolscurrentLocale);
  2. unusualSymbols.setDecimalSeparator '|');
  3. unusualSymbols.setGroupingSeparator '^');
  4.  
  5. String strange =“#,## 0。###”;
  6. DecimalFormat weirdFormatter = new DecimalFormatstrangeunusualSymbols);
  7. weirdFormatter.setGroupingSize4);
  8.  
  9. String bizarre = weirdFormatter.format12345.678);
  10. System.out.println(奇异);

运行时,此示例以奇怪的格式打印数字:

  1. 1 ^ 2345 | 678
  2.  
  3. date
    2018-10-31  12:57:51
  4.  
  5. 参考:
    https://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html#numberpattern
  6.  
  7. DecimalFormat类源码:
  1. /*
  2. * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  3. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  4. */
  5.  
  6. /*
  7. * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  8. * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  9. *
  10. * The original version of this source code and documentation is copyrighted
  11. * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  12. * materials are provided under terms of a License Agreement between Taligent
  13. * and Sun. This technology is protected by multiple US and International
  14. * patents. This notice and attribution to Taligent may not be removed.
  15. * Taligent is a registered trademark of Taligent, Inc.
  16. *
  17. */
  18.  
  19. package java.text;
  20.  
  21. import java.io.IOException;
  22. import java.io.InvalidObjectException;
  23. import java.io.ObjectInputStream;
  24. import java.math.BigDecimal;
  25. import java.math.BigInteger;
  26. import java.math.RoundingMode;
  27. import java.text.spi.NumberFormatProvider;
  28. import java.util.ArrayList;
  29. import java.util.Currency;
  30. import java.util.Locale;
  31. import java.util.ResourceBundle;
  32. import java.util.concurrent.ConcurrentHashMap;
  33. import java.util.concurrent.ConcurrentMap;
  34. import java.util.concurrent.atomic.AtomicInteger;
  35. import java.util.concurrent.atomic.AtomicLong;
  36. import sun.util.locale.provider.LocaleProviderAdapter;
  37. import sun.util.locale.provider.ResourceBundleBasedAdapter;
  38.  
  39. /**
  40. * <code>DecimalFormat</code> is a concrete subclass of
  41. * <code>NumberFormat</code> that formats decimal numbers. It has a variety of
  42. * features designed to make it possible to parse and format numbers in any
  43. * locale, including support for Western, Arabic, and Indic digits. It also
  44. * supports different kinds of numbers, including integers (123), fixed-point
  45. * numbers (123.4), scientific notation (1.23E4), percentages (12%), and
  46. * currency amounts ($123). All of these can be localized.
  47. *
  48. * <p>To obtain a <code>NumberFormat</code> for a specific locale, including the
  49. * default locale, call one of <code>NumberFormat</code>'s factory methods, such
  50. * as <code>getInstance()</code>. In general, do not call the
  51. * <code>DecimalFormat</code> constructors directly, since the
  52. * <code>NumberFormat</code> factory methods may return subclasses other than
  53. * <code>DecimalFormat</code>. If you need to customize the format object, do
  54. * something like this:
  55. *
  56. * <blockquote><pre>
  57. * NumberFormat f = NumberFormat.getInstance(loc);
  58. * if (f instanceof DecimalFormat) {
  59. * ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
  60. * }
  61. * </pre></blockquote>
  62. *
  63. * <p>A <code>DecimalFormat</code> comprises a <em>pattern</em> and a set of
  64. * <em>symbols</em>. The pattern may be set directly using
  65. * <code>applyPattern()</code>, or indirectly using the API methods. The
  66. * symbols are stored in a <code>DecimalFormatSymbols</code> object. When using
  67. * the <code>NumberFormat</code> factory methods, the pattern and symbols are
  68. * read from localized <code>ResourceBundle</code>s.
  69. *
  70. * <h3>Patterns</h3>
  71. *
  72. * <code>DecimalFormat</code> patterns have the following syntax:
  73. * <blockquote><pre>
  74. * <i>Pattern:</i>
  75. * <i>PositivePattern</i>
  76. * <i>PositivePattern</i> ; <i>NegativePattern</i>
  77. * <i>PositivePattern:</i>
  78. * <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>
  79. * <i>NegativePattern:</i>
  80. * <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>
  81. * <i>Prefix:</i>
  82. * any Unicode characters except \uFFFE, \uFFFF, and special characters
  83. * <i>Suffix:</i>
  84. * any Unicode characters except \uFFFE, \uFFFF, and special characters
  85. * <i>Number:</i>
  86. * <i>Integer</i> <i>Exponent<sub>opt</sub></i>
  87. * <i>Integer</i> . <i>Fraction</i> <i>Exponent<sub>opt</sub></i>
  88. * <i>Integer:</i>
  89. * <i>MinimumInteger</i>
  90. * #
  91. * # <i>Integer</i>
  92. * # , <i>Integer</i>
  93. * <i>MinimumInteger:</i>
  94. * 0
  95. * 0 <i>MinimumInteger</i>
  96. * 0 , <i>MinimumInteger</i>
  97. * <i>Fraction:</i>
  98. * <i>MinimumFraction<sub>opt</sub></i> <i>OptionalFraction<sub>opt</sub></i>
  99. * <i>MinimumFraction:</i>
  100. * 0 <i>MinimumFraction<sub>opt</sub></i>
  101. * <i>OptionalFraction:</i>
  102. * # <i>OptionalFraction<sub>opt</sub></i>
  103. * <i>Exponent:</i>
  104. * E <i>MinimumExponent</i>
  105. * <i>MinimumExponent:</i>
  106. * 0 <i>MinimumExponent<sub>opt</sub></i>
  107. * </pre></blockquote>
  108. *
  109. * <p>A <code>DecimalFormat</code> pattern contains a positive and negative
  110. * subpattern, for example, <code>"#,##0.00;(#,##0.00)"</code>. Each
  111. * subpattern has a prefix, numeric part, and suffix. The negative subpattern
  112. * is optional; if absent, then the positive subpattern prefixed with the
  113. * localized minus sign (<code>'-'</code> in most locales) is used as the
  114. * negative subpattern. That is, <code>"0.00"</code> alone is equivalent to
  115. * <code>"0.00;-0.00"</code>. If there is an explicit negative subpattern, it
  116. * serves only to specify the negative prefix and suffix; the number of digits,
  117. * minimal digits, and other characteristics are all the same as the positive
  118. * pattern. That means that <code>"#,##0.0#;(#)"</code> produces precisely
  119. * the same behavior as <code>"#,##0.0#;(#,##0.0#)"</code>.
  120. *
  121. * <p>The prefixes, suffixes, and various symbols used for infinity, digits,
  122. * thousands separators, decimal separators, etc. may be set to arbitrary
  123. * values, and they will appear properly during formatting. However, care must
  124. * be taken that the symbols and strings do not conflict, or parsing will be
  125. * unreliable. For example, either the positive and negative prefixes or the
  126. * suffixes must be distinct for <code>DecimalFormat.parse()</code> to be able
  127. * to distinguish positive from negative values. (If they are identical, then
  128. * <code>DecimalFormat</code> will behave as if no negative subpattern was
  129. * specified.) Another example is that the decimal separator and thousands
  130. * separator should be distinct characters, or parsing will be impossible.
  131. *
  132. * <p>The grouping separator is commonly used for thousands, but in some
  133. * countries it separates ten-thousands. The grouping size is a constant number
  134. * of digits between the grouping characters, such as 3 for 100,000,000 or 4 for
  135. * 1,0000,0000. If you supply a pattern with multiple grouping characters, the
  136. * interval between the last one and the end of the integer is the one that is
  137. * used. So <code>"#,##,###,####"</code> == <code>"######,####"</code> ==
  138. * <code>"##,####,####"</code>.
  139. *
  140. * <h4>Special Pattern Characters</h4>
  141. *
  142. * <p>Many characters in a pattern are taken literally; they are matched during
  143. * parsing and output unchanged during formatting. Special characters, on the
  144. * other hand, stand for other characters, strings, or classes of characters.
  145. * They must be quoted, unless noted otherwise, if they are to appear in the
  146. * prefix or suffix as literals.
  147. *
  148. * <p>The characters listed here are used in non-localized patterns. Localized
  149. * patterns use the corresponding characters taken from this formatter's
  150. * <code>DecimalFormatSymbols</code> object instead, and these characters lose
  151. * their special status. Two exceptions are the currency sign and quote, which
  152. * are not localized.
  153. *
  154. * <blockquote>
  155. * <table class="striped">
  156. * <caption style="display:none">Chart showing symbol, location, localized, and meaning.</caption>
  157. * <thead>
  158. * <tr>
  159. * <th style="text-align:left">Symbol
  160. * <th style="text-align:left">Location
  161. * <th style="text-align:left">Localized?
  162. * <th style="text-align:left">Meaning
  163. * </thead>
  164. * <tbody>
  165. * <tr style="vertical-align:top">
  166. * <td><code>0</code>
  167. * <td>Number
  168. * <td>Yes
  169. * <td>Digit
  170. * <tr style="vertical-align: top">
  171. * <td><code>#</code>
  172. * <td>Number
  173. * <td>Yes
  174. * <td>Digit, zero shows as absent
  175. * <tr style="vertical-align:top">
  176. * <td><code>.</code>
  177. * <td>Number
  178. * <td>Yes
  179. * <td>Decimal separator or monetary decimal separator
  180. * <tr style="vertical-align: top">
  181. * <td><code>-</code>
  182. * <td>Number
  183. * <td>Yes
  184. * <td>Minus sign
  185. * <tr style="vertical-align:top">
  186. * <td><code>,</code>
  187. * <td>Number
  188. * <td>Yes
  189. * <td>Grouping separator
  190. * <tr style="vertical-align: top">
  191. * <td><code>E</code>
  192. * <td>Number
  193. * <td>Yes
  194. * <td>Separates mantissa and exponent in scientific notation.
  195. * <em>Need not be quoted in prefix or suffix.</em>
  196. * <tr style="vertical-align:top">
  197. * <td><code>;</code>
  198. * <td>Subpattern boundary
  199. * <td>Yes
  200. * <td>Separates positive and negative subpatterns
  201. * <tr style="vertical-align: top">
  202. * <td><code>%</code>
  203. * <td>Prefix or suffix
  204. * <td>Yes
  205. * <td>Multiply by 100 and show as percentage
  206. * <tr style="vertical-align:top">
  207. * <td><code>\u2030</code>
  208. * <td>Prefix or suffix
  209. * <td>Yes
  210. * <td>Multiply by 1000 and show as per mille value
  211. * <tr style="vertical-align: top">
  212. * <td><code>¤</code> (<code>\u00A4</code>)
  213. * <td>Prefix or suffix
  214. * <td>No
  215. * <td>Currency sign, replaced by currency symbol. If
  216. * doubled, replaced by international currency symbol.
  217. * If present in a pattern, the monetary decimal separator
  218. * is used instead of the decimal separator.
  219. * <tr style="vertical-align:top">
  220. * <td><code>'</code>
  221. * <td>Prefix or suffix
  222. * <td>No
  223. * <td>Used to quote special characters in a prefix or suffix,
  224. * for example, <code>"'#'#"</code> formats 123 to
  225. * <code>"#123"</code>. To create a single quote
  226. * itself, use two in a row: <code>"# o''clock"</code>.
  227. * </tbody>
  228. * </table>
  229. * </blockquote>
  230. *
  231. * <h4>Scientific Notation</h4>
  232. *
  233. * <p>Numbers in scientific notation are expressed as the product of a mantissa
  234. * and a power of ten, for example, 1234 can be expressed as 1.234 x 10^3. The
  235. * mantissa is often in the range 1.0 &le; x {@literal <} 10.0, but it need not
  236. * be.
  237. * <code>DecimalFormat</code> can be instructed to format and parse scientific
  238. * notation <em>only via a pattern</em>; there is currently no factory method
  239. * that creates a scientific notation format. In a pattern, the exponent
  240. * character immediately followed by one or more digit characters indicates
  241. * scientific notation. Example: <code>"0.###E0"</code> formats the number
  242. * 1234 as <code>"1.234E3"</code>.
  243. *
  244. * <ul>
  245. * <li>The number of digit characters after the exponent character gives the
  246. * minimum exponent digit count. There is no maximum. Negative exponents are
  247. * formatted using the localized minus sign, <em>not</em> the prefix and suffix
  248. * from the pattern. This allows patterns such as <code>"0.###E0 m/s"</code>.
  249. *
  250. * <li>The minimum and maximum number of integer digits are interpreted
  251. * together:
  252. *
  253. * <ul>
  254. * <li>If the maximum number of integer digits is greater than their minimum number
  255. * and greater than 1, it forces the exponent to be a multiple of the maximum
  256. * number of integer digits, and the minimum number of integer digits to be
  257. * interpreted as 1. The most common use of this is to generate
  258. * <em>engineering notation</em>, in which the exponent is a multiple of three,
  259. * e.g., <code>"##0.#####E0"</code>. Using this pattern, the number 12345
  260. * formats to <code>"12.345E3"</code>, and 123456 formats to
  261. * <code>"123.456E3"</code>.
  262. *
  263. * <li>Otherwise, the minimum number of integer digits is achieved by adjusting the
  264. * exponent. Example: 0.00123 formatted with <code>"00.###E0"</code> yields
  265. * <code>"12.3E-4"</code>.
  266. * </ul>
  267. *
  268. * <li>The number of significant digits in the mantissa is the sum of the
  269. * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is
  270. * unaffected by the maximum integer digits. For example, 12345 formatted with
  271. * <code>"##0.##E0"</code> is <code>"12.3E3"</code>. To show all digits, set
  272. * the significant digits count to zero. The number of significant digits
  273. * does not affect parsing.
  274. *
  275. * <li>Exponential patterns may not contain grouping separators.
  276. * </ul>
  277. *
  278. * <h4>Rounding</h4>
  279. *
  280. * <code>DecimalFormat</code> provides rounding modes defined in
  281. * {@link java.math.RoundingMode} for formatting. By default, it uses
  282. * {@link java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}.
  283. *
  284. * <h4>Digits</h4>
  285. *
  286. * For formatting, <code>DecimalFormat</code> uses the ten consecutive
  287. * characters starting with the localized zero digit defined in the
  288. * <code>DecimalFormatSymbols</code> object as digits. For parsing, these
  289. * digits as well as all Unicode decimal digits, as defined by
  290. * {@link Character#digit Character.digit}, are recognized.
  291. *
  292. * <h4>Special Values</h4>
  293. *
  294. * <p><code>NaN</code> is formatted as a string, which typically has a single character
  295. * <code>\uFFFD</code>. This string is determined by the
  296. * <code>DecimalFormatSymbols</code> object. This is the only value for which
  297. * the prefixes and suffixes are not used.
  298. *
  299. * <p>Infinity is formatted as a string, which typically has a single character
  300. * <code>\u221E</code>, with the positive or negative prefixes and suffixes
  301. * applied. The infinity string is determined by the
  302. * <code>DecimalFormatSymbols</code> object.
  303. *
  304. * <p>Negative zero (<code>"-0"</code>) parses to
  305. * <ul>
  306. * <li><code>BigDecimal(0)</code> if <code>isParseBigDecimal()</code> is
  307. * true,
  308. * <li><code>Long(0)</code> if <code>isParseBigDecimal()</code> is false
  309. * and <code>isParseIntegerOnly()</code> is true,
  310. * <li><code>Double(-0.0)</code> if both <code>isParseBigDecimal()</code>
  311. * and <code>isParseIntegerOnly()</code> are false.
  312. * </ul>
  313. *
  314. * <h4><a id="synchronization">Synchronization</a></h4>
  315. *
  316. * <p>
  317. * Decimal formats are generally not synchronized.
  318. * It is recommended to create separate format instances for each thread.
  319. * If multiple threads access a format concurrently, it must be synchronized
  320. * externally.
  321. *
  322. * <h4>Example</h4>
  323. *
  324. * <blockquote><pre>{@code
  325. * <strong>// Print out a number using the localized number, integer, currency,
  326. * // and percent format for each locale</strong>
  327. * Locale[] locales = NumberFormat.getAvailableLocales();
  328. * double myNumber = -1234.56;
  329. * NumberFormat form;
  330. * for (int j = 0; j < 4; ++j) {
  331. * System.out.println("FORMAT");
  332. * for (int i = 0; i < locales.length; ++i) {
  333. * if (locales[i].getCountry().length() == 0) {
  334. * continue; // Skip language-only locales
  335. * }
  336. * System.out.print(locales[i].getDisplayName());
  337. * switch (j) {
  338. * case 0:
  339. * form = NumberFormat.getInstance(locales[i]); break;
  340. * case 1:
  341. * form = NumberFormat.getIntegerInstance(locales[i]); break;
  342. * case 2:
  343. * form = NumberFormat.getCurrencyInstance(locales[i]); break;
  344. * default:
  345. * form = NumberFormat.getPercentInstance(locales[i]); break;
  346. * }
  347. * if (form instanceof DecimalFormat) {
  348. * System.out.print(": " + ((DecimalFormat) form).toPattern());
  349. * }
  350. * System.out.print(" -> " + form.format(myNumber));
  351. * try {
  352. * System.out.println(" -> " + form.parse(form.format(myNumber)));
  353. * } catch (ParseException e) {}
  354. * }
  355. * }
  356. * }</pre></blockquote>
  357. *
  358. * @see <a href="http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html">Java Tutorial</a>
  359. * @see NumberFormat
  360. * @see DecimalFormatSymbols
  361. * @see ParsePosition
  362. * @author Mark Davis
  363. * @author Alan Liu
  364. * @since 1.1
  365. */
  366. public class DecimalFormat extends NumberFormat {
  367.  
  368. /**
  369. * Creates a DecimalFormat using the default pattern and symbols
  370. * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale.
  371. * This is a convenient way to obtain a
  372. * DecimalFormat when internationalization is not the main concern.
  373. * <p>
  374. * To obtain standard formats for a given locale, use the factory methods
  375. * on NumberFormat such as getNumberInstance. These factories will
  376. * return the most appropriate sub-class of NumberFormat for a given
  377. * locale.
  378. *
  379. * @see java.text.NumberFormat#getInstance
  380. * @see java.text.NumberFormat#getNumberInstance
  381. * @see java.text.NumberFormat#getCurrencyInstance
  382. * @see java.text.NumberFormat#getPercentInstance
  383. */
  384. public DecimalFormat() {
  385. // Get the pattern for the default locale.
  386. Locale def = Locale.getDefault(Locale.Category.FORMAT);
  387. LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(NumberFormatProvider.class, def);
  388. if (!(adapter instanceof ResourceBundleBasedAdapter)) {
  389. adapter = LocaleProviderAdapter.getResourceBundleBased();
  390. }
  391. String[] all = adapter.getLocaleResources(def).getNumberPatterns();
  392.  
  393. // Always applyPattern after the symbols are set
  394. this.symbols = DecimalFormatSymbols.getInstance(def);
  395. applyPattern(all[0], false);
  396. }
  397.  
  398. /**
  399. * Creates a DecimalFormat using the given pattern and the symbols
  400. * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale.
  401. * This is a convenient way to obtain a
  402. * DecimalFormat when internationalization is not the main concern.
  403. * <p>
  404. * To obtain standard formats for a given locale, use the factory methods
  405. * on NumberFormat such as getNumberInstance. These factories will
  406. * return the most appropriate sub-class of NumberFormat for a given
  407. * locale.
  408. *
  409. * @param pattern a non-localized pattern string.
  410. * @exception NullPointerException if <code>pattern</code> is null
  411. * @exception IllegalArgumentException if the given pattern is invalid.
  412. * @see java.text.NumberFormat#getInstance
  413. * @see java.text.NumberFormat#getNumberInstance
  414. * @see java.text.NumberFormat#getCurrencyInstance
  415. * @see java.text.NumberFormat#getPercentInstance
  416. */
  417. public DecimalFormat(String pattern) {
  418. // Always applyPattern after the symbols are set
  419. this.symbols = DecimalFormatSymbols.getInstance(Locale.getDefault(Locale.Category.FORMAT));
  420. applyPattern(pattern, false);
  421. }
  422.  
  423. /**
  424. * Creates a DecimalFormat using the given pattern and symbols.
  425. * Use this constructor when you need to completely customize the
  426. * behavior of the format.
  427. * <p>
  428. * To obtain standard formats for a given
  429. * locale, use the factory methods on NumberFormat such as
  430. * getInstance or getCurrencyInstance. If you need only minor adjustments
  431. * to a standard format, you can modify the format returned by
  432. * a NumberFormat factory method.
  433. *
  434. * @param pattern a non-localized pattern string
  435. * @param symbols the set of symbols to be used
  436. * @exception NullPointerException if any of the given arguments is null
  437. * @exception IllegalArgumentException if the given pattern is invalid
  438. * @see java.text.NumberFormat#getInstance
  439. * @see java.text.NumberFormat#getNumberInstance
  440. * @see java.text.NumberFormat#getCurrencyInstance
  441. * @see java.text.NumberFormat#getPercentInstance
  442. * @see java.text.DecimalFormatSymbols
  443. */
  444. public DecimalFormat (String pattern, DecimalFormatSymbols symbols) {
  445. // Always applyPattern after the symbols are set
  446. this.symbols = (DecimalFormatSymbols)symbols.clone();
  447. applyPattern(pattern, false);
  448. }
  449.  
  450. // Overrides
  451. /**
  452. * Formats a number and appends the resulting text to the given string
  453. * buffer.
  454. * The number can be of any subclass of {@link java.lang.Number}.
  455. * <p>
  456. * This implementation uses the maximum precision permitted.
  457. * @param number the number to format
  458. * @param toAppendTo the <code>StringBuffer</code> to which the formatted
  459. * text is to be appended
  460. * @param pos On input: an alignment field, if desired.
  461. * On output: the offsets of the alignment field.
  462. * @return the value passed in as <code>toAppendTo</code>
  463. * @exception IllegalArgumentException if <code>number</code> is
  464. * null or not an instance of <code>Number</code>.
  465. * @exception NullPointerException if <code>toAppendTo</code> or
  466. * <code>pos</code> is null
  467. * @exception ArithmeticException if rounding is needed with rounding
  468. * mode being set to RoundingMode.UNNECESSARY
  469. * @see java.text.FieldPosition
  470. */
  471. @Override
  472. public final StringBuffer format(Object number,
  473. StringBuffer toAppendTo,
  474. FieldPosition pos) {
  475. if (number instanceof Long || number instanceof Integer ||
  476. number instanceof Short || number instanceof Byte ||
  477. number instanceof AtomicInteger ||
  478. number instanceof AtomicLong ||
  479. (number instanceof BigInteger &&
  480. ((BigInteger)number).bitLength () < 64)) {
  481. return format(((Number)number).longValue(), toAppendTo, pos);
  482. } else if (number instanceof BigDecimal) {
  483. return format((BigDecimal)number, toAppendTo, pos);
  484. } else if (number instanceof BigInteger) {
  485. return format((BigInteger)number, toAppendTo, pos);
  486. } else if (number instanceof Number) {
  487. return format(((Number)number).doubleValue(), toAppendTo, pos);
  488. } else {
  489. throw new IllegalArgumentException("Cannot format given Object as a Number");
  490. }
  491. }
  492.  
  493. /**
  494. * Formats a double to produce a string.
  495. * @param number The double to format
  496. * @param result where the text is to be appended
  497. * @param fieldPosition On input: an alignment field, if desired.
  498. * On output: the offsets of the alignment field.
  499. * @exception NullPointerException if {@code result} or
  500. * {@code fieldPosition} is {@code null}
  501. * @exception ArithmeticException if rounding is needed with rounding
  502. * mode being set to RoundingMode.UNNECESSARY
  503. * @return The formatted number string
  504. * @see java.text.FieldPosition
  505. */
  506. @Override
  507. public StringBuffer format(double number, StringBuffer result,
  508. FieldPosition fieldPosition) {
  509. // If fieldPosition is a DontCareFieldPosition instance we can
  510. // try to go to fast-path code.
  511. boolean tryFastPath = false;
  512. if (fieldPosition == DontCareFieldPosition.INSTANCE)
  513. tryFastPath = true;
  514. else {
  515. fieldPosition.setBeginIndex(0);
  516. fieldPosition.setEndIndex(0);
  517. }
  518.  
  519. if (tryFastPath) {
  520. String tempResult = fastFormat(number);
  521. if (tempResult != null) {
  522. result.append(tempResult);
  523. return result;
  524. }
  525. }
  526.  
  527. // if fast-path could not work, we fallback to standard code.
  528. return format(number, result, fieldPosition.getFieldDelegate());
  529. }
  530.  
  531. /**
  532. * Formats a double to produce a string.
  533. * @param number The double to format
  534. * @param result where the text is to be appended
  535. * @param delegate notified of locations of sub fields
  536. * @exception ArithmeticException if rounding is needed with rounding
  537. * mode being set to RoundingMode.UNNECESSARY
  538. * @return The formatted number string
  539. */
  540. private StringBuffer format(double number, StringBuffer result,
  541. FieldDelegate delegate) {
  542. if (Double.isNaN(number) ||
  543. (Double.isInfinite(number) && multiplier == 0)) {
  544. int iFieldStart = result.length();
  545. result.append(symbols.getNaN());
  546. delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
  547. iFieldStart, result.length(), result);
  548. return result;
  549. }
  550.  
  551. /* Detecting whether a double is negative is easy with the exception of
  552. * the value -0.0. This is a double which has a zero mantissa (and
  553. * exponent), but a negative sign bit. It is semantically distinct from
  554. * a zero with a positive sign bit, and this distinction is important
  555. * to certain kinds of computations. However, it's a little tricky to
  556. * detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you may
  557. * ask, does it behave distinctly from +0.0? Well, 1/(-0.0) ==
  558. * -Infinity. Proper detection of -0.0 is needed to deal with the
  559. * issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
  560. */
  561. boolean isNegative = ((number < 0.0) || (number == 0.0 && 1/number < 0.0)) ^ (multiplier < 0);
  562.  
  563. if (multiplier != 1) {
  564. number *= multiplier;
  565. }
  566.  
  567. if (Double.isInfinite(number)) {
  568. if (isNegative) {
  569. append(result, negativePrefix, delegate,
  570. getNegativePrefixFieldPositions(), Field.SIGN);
  571. } else {
  572. append(result, positivePrefix, delegate,
  573. getPositivePrefixFieldPositions(), Field.SIGN);
  574. }
  575.  
  576. int iFieldStart = result.length();
  577. result.append(symbols.getInfinity());
  578. delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
  579. iFieldStart, result.length(), result);
  580.  
  581. if (isNegative) {
  582. append(result, negativeSuffix, delegate,
  583. getNegativeSuffixFieldPositions(), Field.SIGN);
  584. } else {
  585. append(result, positiveSuffix, delegate,
  586. getPositiveSuffixFieldPositions(), Field.SIGN);
  587. }
  588.  
  589. return result;
  590. }
  591.  
  592. if (isNegative) {
  593. number = -number;
  594. }
  595.  
  596. // at this point we are guaranteed a nonnegative finite number.
  597. assert(number >= 0 && !Double.isInfinite(number));
  598.  
  599. synchronized(digitList) {
  600. int maxIntDigits = super.getMaximumIntegerDigits();
  601. int minIntDigits = super.getMinimumIntegerDigits();
  602. int maxFraDigits = super.getMaximumFractionDigits();
  603. int minFraDigits = super.getMinimumFractionDigits();
  604.  
  605. digitList.set(isNegative, number, useExponentialNotation ?
  606. maxIntDigits + maxFraDigits : maxFraDigits,
  607. !useExponentialNotation);
  608. return subformat(result, delegate, isNegative, false,
  609. maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
  610. }
  611. }
  612.  
  613. /**
  614. * Format a long to produce a string.
  615. * @param number The long to format
  616. * @param result where the text is to be appended
  617. * @param fieldPosition On input: an alignment field, if desired.
  618. * On output: the offsets of the alignment field.
  619. * @exception NullPointerException if {@code result} or
  620. * {@code fieldPosition} is {@code null}
  621. * @exception ArithmeticException if rounding is needed with rounding
  622. * mode being set to RoundingMode.UNNECESSARY
  623. * @return The formatted number string
  624. * @see java.text.FieldPosition
  625. */
  626. @Override
  627. public StringBuffer format(long number, StringBuffer result,
  628. FieldPosition fieldPosition) {
  629. fieldPosition.setBeginIndex(0);
  630. fieldPosition.setEndIndex(0);
  631.  
  632. return format(number, result, fieldPosition.getFieldDelegate());
  633. }
  634.  
  635. /**
  636. * Format a long to produce a string.
  637. * @param number The long to format
  638. * @param result where the text is to be appended
  639. * @param delegate notified of locations of sub fields
  640. * @return The formatted number string
  641. * @exception ArithmeticException if rounding is needed with rounding
  642. * mode being set to RoundingMode.UNNECESSARY
  643. * @see java.text.FieldPosition
  644. */
  645. private StringBuffer format(long number, StringBuffer result,
  646. FieldDelegate delegate) {
  647. boolean isNegative = (number < 0);
  648. if (isNegative) {
  649. number = -number;
  650. }
  651.  
  652. // In general, long values always represent real finite numbers, so
  653. // we don't have to check for +/- Infinity or NaN. However, there
  654. // is one case we have to be careful of: The multiplier can push
  655. // a number near MIN_VALUE or MAX_VALUE outside the legal range. We
  656. // check for this before multiplying, and if it happens we use
  657. // BigInteger instead.
  658. boolean useBigInteger = false;
  659. if (number < 0) { // This can only happen if number == Long.MIN_VALUE.
  660. if (multiplier != 0) {
  661. useBigInteger = true;
  662. }
  663. } else if (multiplier != 1 && multiplier != 0) {
  664. long cutoff = Long.MAX_VALUE / multiplier;
  665. if (cutoff < 0) {
  666. cutoff = -cutoff;
  667. }
  668. useBigInteger = (number > cutoff);
  669. }
  670.  
  671. if (useBigInteger) {
  672. if (isNegative) {
  673. number = -number;
  674. }
  675. BigInteger bigIntegerValue = BigInteger.valueOf(number);
  676. return format(bigIntegerValue, result, delegate, true);
  677. }
  678.  
  679. number *= multiplier;
  680. if (number == 0) {
  681. isNegative = false;
  682. } else {
  683. if (multiplier < 0) {
  684. number = -number;
  685. isNegative = !isNegative;
  686. }
  687. }
  688.  
  689. synchronized(digitList) {
  690. int maxIntDigits = super.getMaximumIntegerDigits();
  691. int minIntDigits = super.getMinimumIntegerDigits();
  692. int maxFraDigits = super.getMaximumFractionDigits();
  693. int minFraDigits = super.getMinimumFractionDigits();
  694.  
  695. digitList.set(isNegative, number,
  696. useExponentialNotation ? maxIntDigits + maxFraDigits : 0);
  697.  
  698. return subformat(result, delegate, isNegative, true,
  699. maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
  700. }
  701. }
  702.  
  703. /**
  704. * Formats a BigDecimal to produce a string.
  705. * @param number The BigDecimal to format
  706. * @param result where the text is to be appended
  707. * @param fieldPosition On input: an alignment field, if desired.
  708. * On output: the offsets of the alignment field.
  709. * @return The formatted number string
  710. * @exception ArithmeticException if rounding is needed with rounding
  711. * mode being set to RoundingMode.UNNECESSARY
  712. * @see java.text.FieldPosition
  713. */
  714. private StringBuffer format(BigDecimal number, StringBuffer result,
  715. FieldPosition fieldPosition) {
  716. fieldPosition.setBeginIndex(0);
  717. fieldPosition.setEndIndex(0);
  718. return format(number, result, fieldPosition.getFieldDelegate());
  719. }
  720.  
  721. /**
  722. * Formats a BigDecimal to produce a string.
  723. * @param number The BigDecimal to format
  724. * @param result where the text is to be appended
  725. * @param delegate notified of locations of sub fields
  726. * @exception ArithmeticException if rounding is needed with rounding
  727. * mode being set to RoundingMode.UNNECESSARY
  728. * @return The formatted number string
  729. */
  730. private StringBuffer format(BigDecimal number, StringBuffer result,
  731. FieldDelegate delegate) {
  732. if (multiplier != 1) {
  733. number = number.multiply(getBigDecimalMultiplier());
  734. }
  735. boolean isNegative = number.signum() == -1;
  736. if (isNegative) {
  737. number = number.negate();
  738. }
  739.  
  740. synchronized(digitList) {
  741. int maxIntDigits = getMaximumIntegerDigits();
  742. int minIntDigits = getMinimumIntegerDigits();
  743. int maxFraDigits = getMaximumFractionDigits();
  744. int minFraDigits = getMinimumFractionDigits();
  745. int maximumDigits = maxIntDigits + maxFraDigits;
  746.  
  747. digitList.set(isNegative, number, useExponentialNotation ?
  748. ((maximumDigits < 0) ? Integer.MAX_VALUE : maximumDigits) :
  749. maxFraDigits, !useExponentialNotation);
  750.  
  751. return subformat(result, delegate, isNegative, false,
  752. maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
  753. }
  754. }
  755.  
  756. /**
  757. * Format a BigInteger to produce a string.
  758. * @param number The BigInteger to format
  759. * @param result where the text is to be appended
  760. * @param fieldPosition On input: an alignment field, if desired.
  761. * On output: the offsets of the alignment field.
  762. * @return The formatted number string
  763. * @exception ArithmeticException if rounding is needed with rounding
  764. * mode being set to RoundingMode.UNNECESSARY
  765. * @see java.text.FieldPosition
  766. */
  767. private StringBuffer format(BigInteger number, StringBuffer result,
  768. FieldPosition fieldPosition) {
  769. fieldPosition.setBeginIndex(0);
  770. fieldPosition.setEndIndex(0);
  771.  
  772. return format(number, result, fieldPosition.getFieldDelegate(), false);
  773. }
  774.  
  775. /**
  776. * Format a BigInteger to produce a string.
  777. * @param number The BigInteger to format
  778. * @param result where the text is to be appended
  779. * @param delegate notified of locations of sub fields
  780. * @return The formatted number string
  781. * @exception ArithmeticException if rounding is needed with rounding
  782. * mode being set to RoundingMode.UNNECESSARY
  783. * @see java.text.FieldPosition
  784. */
  785. private StringBuffer format(BigInteger number, StringBuffer result,
  786. FieldDelegate delegate, boolean formatLong) {
  787. if (multiplier != 1) {
  788. number = number.multiply(getBigIntegerMultiplier());
  789. }
  790. boolean isNegative = number.signum() == -1;
  791. if (isNegative) {
  792. number = number.negate();
  793. }
  794.  
  795. synchronized(digitList) {
  796. int maxIntDigits, minIntDigits, maxFraDigits, minFraDigits, maximumDigits;
  797. if (formatLong) {
  798. maxIntDigits = super.getMaximumIntegerDigits();
  799. minIntDigits = super.getMinimumIntegerDigits();
  800. maxFraDigits = super.getMaximumFractionDigits();
  801. minFraDigits = super.getMinimumFractionDigits();
  802. maximumDigits = maxIntDigits + maxFraDigits;
  803. } else {
  804. maxIntDigits = getMaximumIntegerDigits();
  805. minIntDigits = getMinimumIntegerDigits();
  806. maxFraDigits = getMaximumFractionDigits();
  807. minFraDigits = getMinimumFractionDigits();
  808. maximumDigits = maxIntDigits + maxFraDigits;
  809. if (maximumDigits < 0) {
  810. maximumDigits = Integer.MAX_VALUE;
  811. }
  812. }
  813.  
  814. digitList.set(isNegative, number,
  815. useExponentialNotation ? maximumDigits : 0);
  816.  
  817. return subformat(result, delegate, isNegative, true,
  818. maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
  819. }
  820. }
  821.  
  822. /**
  823. * Formats an Object producing an <code>AttributedCharacterIterator</code>.
  824. * You can use the returned <code>AttributedCharacterIterator</code>
  825. * to build the resulting String, as well as to determine information
  826. * about the resulting String.
  827. * <p>
  828. * Each attribute key of the AttributedCharacterIterator will be of type
  829. * <code>NumberFormat.Field</code>, with the attribute value being the
  830. * same as the attribute key.
  831. *
  832. * @exception NullPointerException if obj is null.
  833. * @exception IllegalArgumentException when the Format cannot format the
  834. * given object.
  835. * @exception ArithmeticException if rounding is needed with rounding
  836. * mode being set to RoundingMode.UNNECESSARY
  837. * @param obj The object to format
  838. * @return AttributedCharacterIterator describing the formatted value.
  839. * @since 1.4
  840. */
  841. @Override
  842. public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
  843. CharacterIteratorFieldDelegate delegate =
  844. new CharacterIteratorFieldDelegate();
  845. StringBuffer sb = new StringBuffer();
  846.  
  847. if (obj instanceof Double || obj instanceof Float) {
  848. format(((Number)obj).doubleValue(), sb, delegate);
  849. } else if (obj instanceof Long || obj instanceof Integer ||
  850. obj instanceof Short || obj instanceof Byte ||
  851. obj instanceof AtomicInteger || obj instanceof AtomicLong) {
  852. format(((Number)obj).longValue(), sb, delegate);
  853. } else if (obj instanceof BigDecimal) {
  854. format((BigDecimal)obj, sb, delegate);
  855. } else if (obj instanceof BigInteger) {
  856. format((BigInteger)obj, sb, delegate, false);
  857. } else if (obj == null) {
  858. throw new NullPointerException(
  859. "formatToCharacterIterator must be passed non-null object");
  860. } else {
  861. throw new IllegalArgumentException(
  862. "Cannot format given Object as a Number");
  863. }
  864. return delegate.getIterator(sb.toString());
  865. }
  866.  
  867. // ==== Begin fast-path formating logic for double =========================
  868.  
  869. /* Fast-path formatting will be used for format(double ...) methods iff a
  870. * number of conditions are met (see checkAndSetFastPathStatus()):
  871. * - Only if instance properties meet the right predefined conditions.
  872. * - The abs value of the double to format is <= Integer.MAX_VALUE.
  873. *
  874. * The basic approach is to split the binary to decimal conversion of a
  875. * double value into two phases:
  876. * * The conversion of the integer portion of the double.
  877. * * The conversion of the fractional portion of the double
  878. * (limited to two or three digits).
  879. *
  880. * The isolation and conversion of the integer portion of the double is
  881. * straightforward. The conversion of the fraction is more subtle and relies
  882. * on some rounding properties of double to the decimal precisions in
  883. * question. Using the terminology of BigDecimal, this fast-path algorithm
  884. * is applied when a double value has a magnitude less than Integer.MAX_VALUE
  885. * and rounding is to nearest even and the destination format has two or
  886. * three digits of *scale* (digits after the decimal point).
  887. *
  888. * Under a rounding to nearest even policy, the returned result is a digit
  889. * string of a number in the (in this case decimal) destination format
  890. * closest to the exact numerical value of the (in this case binary) input
  891. * value. If two destination format numbers are equally distant, the one
  892. * with the last digit even is returned. To compute such a correctly rounded
  893. * value, some information about digits beyond the smallest returned digit
  894. * position needs to be consulted.
  895. *
  896. * In general, a guard digit, a round digit, and a sticky *bit* are needed
  897. * beyond the returned digit position. If the discarded portion of the input
  898. * is sufficiently large, the returned digit string is incremented. In round
  899. * to nearest even, this threshold to increment occurs near the half-way
  900. * point between digits. The sticky bit records if there are any remaining
  901. * trailing digits of the exact input value in the new format; the sticky bit
  902. * is consulted only in close to half-way rounding cases.
  903. *
  904. * Given the computation of the digit and bit values, rounding is then
  905. * reduced to a table lookup problem. For decimal, the even/odd cases look
  906. * like this:
  907. *
  908. * Last Round Sticky
  909. * 6 5 0 => 6 // exactly halfway, return even digit.
  910. * 6 5 1 => 7 // a little bit more than halfway, round up.
  911. * 7 5 0 => 8 // exactly halfway, round up to even.
  912. * 7 5 1 => 8 // a little bit more than halfway, round up.
  913. * With analogous entries for other even and odd last-returned digits.
  914. *
  915. * However, decimal negative powers of 5 smaller than 0.5 are *not* exactly
  916. * representable as binary fraction. In particular, 0.005 (the round limit
  917. * for a two-digit scale) and 0.0005 (the round limit for a three-digit
  918. * scale) are not representable. Therefore, for input values near these cases
  919. * the sticky bit is known to be set which reduces the rounding logic to:
  920. *
  921. * Last Round Sticky
  922. * 6 5 1 => 7 // a little bit more than halfway, round up.
  923. * 7 5 1 => 8 // a little bit more than halfway, round up.
  924. *
  925. * In other words, if the round digit is 5, the sticky bit is known to be
  926. * set. If the round digit is something other than 5, the sticky bit is not
  927. * relevant. Therefore, some of the logic about whether or not to increment
  928. * the destination *decimal* value can occur based on tests of *binary*
  929. * computations of the binary input number.
  930. */
  931.  
  932. /**
  933. * Check validity of using fast-path for this instance. If fast-path is valid
  934. * for this instance, sets fast-path state as true and initializes fast-path
  935. * utility fields as needed.
  936. *
  937. * This method is supposed to be called rarely, otherwise that will break the
  938. * fast-path performance. That means avoiding frequent changes of the
  939. * properties of the instance, since for most properties, each time a change
  940. * happens, a call to this method is needed at the next format call.
  941. *
  942. * FAST-PATH RULES:
  943. * Similar to the default DecimalFormat instantiation case.
  944. * More precisely:
  945. * - HALF_EVEN rounding mode,
  946. * - isGroupingUsed() is true,
  947. * - groupingSize of 3,
  948. * - multiplier is 1,
  949. * - Decimal separator not mandatory,
  950. * - No use of exponential notation,
  951. * - minimumIntegerDigits is exactly 1 and maximumIntegerDigits at least 10
  952. * - For number of fractional digits, the exact values found in the default case:
  953. * Currency : min = max = 2.
  954. * Decimal : min = 0. max = 3.
  955. *
  956. */
  957. private boolean checkAndSetFastPathStatus() {
  958.  
  959. boolean fastPathWasOn = isFastPath;
  960.  
  961. if ((roundingMode == RoundingMode.HALF_EVEN) &&
  962. (isGroupingUsed()) &&
  963. (groupingSize == 3) &&
  964. (multiplier == 1) &&
  965. (!decimalSeparatorAlwaysShown) &&
  966. (!useExponentialNotation)) {
  967.  
  968. // The fast-path algorithm is semi-hardcoded against
  969. // minimumIntegerDigits and maximumIntegerDigits.
  970. isFastPath = ((minimumIntegerDigits == 1) &&
  971. (maximumIntegerDigits >= 10));
  972.  
  973. // The fast-path algorithm is hardcoded against
  974. // minimumFractionDigits and maximumFractionDigits.
  975. if (isFastPath) {
  976. if (isCurrencyFormat) {
  977. if ((minimumFractionDigits != 2) ||
  978. (maximumFractionDigits != 2))
  979. isFastPath = false;
  980. } else if ((minimumFractionDigits != 0) ||
  981. (maximumFractionDigits != 3))
  982. isFastPath = false;
  983. }
  984. } else
  985. isFastPath = false;
  986.  
  987. resetFastPathData(fastPathWasOn);
  988. fastPathCheckNeeded = false;
  989.  
  990. /*
  991. * Returns true after successfully checking the fast path condition and
  992. * setting the fast path data. The return value is used by the
  993. * fastFormat() method to decide whether to call the resetFastPathData
  994. * method to reinitialize fast path data or is it already initialized
  995. * in this method.
  996. */
  997. return true;
  998. }
  999.  
  1000. private void resetFastPathData(boolean fastPathWasOn) {
  1001. // Since some instance properties may have changed while still falling
  1002. // in the fast-path case, we need to reinitialize fastPathData anyway.
  1003. if (isFastPath) {
  1004. // We need to instantiate fastPathData if not already done.
  1005. if (fastPathData == null) {
  1006. fastPathData = new FastPathData();
  1007. }
  1008.  
  1009. // Sets up the locale specific constants used when formatting.
  1010. // '0' is our default representation of zero.
  1011. fastPathData.zeroDelta = symbols.getZeroDigit() - '0';
  1012. fastPathData.groupingChar = symbols.getGroupingSeparator();
  1013.  
  1014. // Sets up fractional constants related to currency/decimal pattern.
  1015. fastPathData.fractionalMaxIntBound = (isCurrencyFormat)
  1016. ? 99 : 999;
  1017. fastPathData.fractionalScaleFactor = (isCurrencyFormat)
  1018. ? 100.0d : 1000.0d;
  1019.  
  1020. // Records the need for adding prefix or suffix
  1021. fastPathData.positiveAffixesRequired
  1022. = (positivePrefix.length() != 0)
  1023. || (positiveSuffix.length() != 0);
  1024. fastPathData.negativeAffixesRequired
  1025. = (negativePrefix.length() != 0)
  1026. || (negativeSuffix.length() != 0);
  1027.  
  1028. // Creates a cached char container for result, with max possible size.
  1029. int maxNbIntegralDigits = 10;
  1030. int maxNbGroups = 3;
  1031. int containerSize
  1032. = Math.max(positivePrefix.length(), negativePrefix.length())
  1033. + maxNbIntegralDigits + maxNbGroups + 1
  1034. + maximumFractionDigits
  1035. + Math.max(positiveSuffix.length(), negativeSuffix.length());
  1036.  
  1037. fastPathData.fastPathContainer = new char[containerSize];
  1038.  
  1039. // Sets up prefix and suffix char arrays constants.
  1040. fastPathData.charsPositiveSuffix = positiveSuffix.toCharArray();
  1041. fastPathData.charsNegativeSuffix = negativeSuffix.toCharArray();
  1042. fastPathData.charsPositivePrefix = positivePrefix.toCharArray();
  1043. fastPathData.charsNegativePrefix = negativePrefix.toCharArray();
  1044.  
  1045. // Sets up fixed index positions for integral and fractional digits.
  1046. // Sets up decimal point in cached result container.
  1047. int longestPrefixLength
  1048. = Math.max(positivePrefix.length(),
  1049. negativePrefix.length());
  1050. int decimalPointIndex
  1051. = maxNbIntegralDigits + maxNbGroups + longestPrefixLength;
  1052.  
  1053. fastPathData.integralLastIndex = decimalPointIndex - 1;
  1054. fastPathData.fractionalFirstIndex = decimalPointIndex + 1;
  1055. fastPathData.fastPathContainer[decimalPointIndex]
  1056. = isCurrencyFormat
  1057. ? symbols.getMonetaryDecimalSeparator()
  1058. : symbols.getDecimalSeparator();
  1059.  
  1060. } else if (fastPathWasOn) {
  1061. // Previous state was fast-path and is no more.
  1062. // Resets cached array constants.
  1063. fastPathData.fastPathContainer = null;
  1064. fastPathData.charsPositiveSuffix = null;
  1065. fastPathData.charsNegativeSuffix = null;
  1066. fastPathData.charsPositivePrefix = null;
  1067. fastPathData.charsNegativePrefix = null;
  1068. }
  1069. }
  1070.  
  1071. /**
  1072. * Returns true if rounding-up must be done on {@code scaledFractionalPartAsInt},
  1073. * false otherwise.
  1074. *
  1075. * This is a utility method that takes correct half-even rounding decision on
  1076. * passed fractional value at the scaled decimal point (2 digits for currency
  1077. * case and 3 for decimal case), when the approximated fractional part after
  1078. * scaled decimal point is exactly 0.5d. This is done by means of exact
  1079. * calculations on the {@code fractionalPart} floating-point value.
  1080. *
  1081. * This method is supposed to be called by private {@code fastDoubleFormat}
  1082. * method only.
  1083. *
  1084. * The algorithms used for the exact calculations are :
  1085. *
  1086. * The <b><i>FastTwoSum</i></b> algorithm, from T.J.Dekker, described in the
  1087. * papers "<i>A Floating-Point Technique for Extending the Available
  1088. * Precision</i>" by Dekker, and in "<i>Adaptive Precision Floating-Point
  1089. * Arithmetic and Fast Robust Geometric Predicates</i>" from J.Shewchuk.
  1090. *
  1091. * A modified version of <b><i>Sum2S</i></b> cascaded summation described in
  1092. * "<i>Accurate Sum and Dot Product</i>" from Takeshi Ogita and All. As
  1093. * Ogita says in this paper this is an equivalent of the Kahan-Babuska's
  1094. * summation algorithm because we order the terms by magnitude before summing
  1095. * them. For this reason we can use the <i>FastTwoSum</i> algorithm rather
  1096. * than the more expensive Knuth's <i>TwoSum</i>.
  1097. *
  1098. * We do this to avoid a more expensive exact "<i>TwoProduct</i>" algorithm,
  1099. * like those described in Shewchuk's paper above. See comments in the code
  1100. * below.
  1101. *
  1102. * @param fractionalPart The fractional value on which we take rounding
  1103. * decision.
  1104. * @param scaledFractionalPartAsInt The integral part of the scaled
  1105. * fractional value.
  1106. *
  1107. * @return the decision that must be taken regarding half-even rounding.
  1108. */
  1109. private boolean exactRoundUp(double fractionalPart,
  1110. int scaledFractionalPartAsInt) {
  1111.  
  1112. /* exactRoundUp() method is called by fastDoubleFormat() only.
  1113. * The precondition expected to be verified by the passed parameters is :
  1114. * scaledFractionalPartAsInt ==
  1115. * (int) (fractionalPart * fastPathData.fractionalScaleFactor).
  1116. * This is ensured by fastDoubleFormat() code.
  1117. */
  1118.  
  1119. /* We first calculate roundoff error made by fastDoubleFormat() on
  1120. * the scaled fractional part. We do this with exact calculation on the
  1121. * passed fractionalPart. Rounding decision will then be taken from roundoff.
  1122. */
  1123.  
  1124. /* ---- TwoProduct(fractionalPart, scale factor (i.e. 1000.0d or 100.0d)).
  1125. *
  1126. * The below is an optimized exact "TwoProduct" calculation of passed
  1127. * fractional part with scale factor, using Ogita's Sum2S cascaded
  1128. * summation adapted as Kahan-Babuska equivalent by using FastTwoSum
  1129. * (much faster) rather than Knuth's TwoSum.
  1130. *
  1131. * We can do this because we order the summation from smallest to
  1132. * greatest, so that FastTwoSum can be used without any additional error.
  1133. *
  1134. * The "TwoProduct" exact calculation needs 17 flops. We replace this by
  1135. * a cascaded summation of FastTwoSum calculations, each involving an
  1136. * exact multiply by a power of 2.
  1137. *
  1138. * Doing so saves overall 4 multiplications and 1 addition compared to
  1139. * using traditional "TwoProduct".
  1140. *
  1141. * The scale factor is either 100 (currency case) or 1000 (decimal case).
  1142. * - when 1000, we replace it by (1024 - 16 - 8) = 1000.
  1143. * - when 100, we replace it by (128 - 32 + 4) = 100.
  1144. * Every multiplication by a power of 2 (1024, 128, 32, 16, 8, 4) is exact.
  1145. *
  1146. */
  1147. double approxMax; // Will always be positive.
  1148. double approxMedium; // Will always be negative.
  1149. double approxMin;
  1150.  
  1151. double fastTwoSumApproximation = 0.0d;
  1152. double fastTwoSumRoundOff = 0.0d;
  1153. double bVirtual = 0.0d;
  1154.  
  1155. if (isCurrencyFormat) {
  1156. // Scale is 100 = 128 - 32 + 4.
  1157. // Multiply by 2**n is a shift. No roundoff. No error.
  1158. approxMax = fractionalPart * 128.00d;
  1159. approxMedium = - (fractionalPart * 32.00d);
  1160. approxMin = fractionalPart * 4.00d;
  1161. } else {
  1162. // Scale is 1000 = 1024 - 16 - 8.
  1163. // Multiply by 2**n is a shift. No roundoff. No error.
  1164. approxMax = fractionalPart * 1024.00d;
  1165. approxMedium = - (fractionalPart * 16.00d);
  1166. approxMin = - (fractionalPart * 8.00d);
  1167. }
  1168.  
  1169. // Shewchuk/Dekker's FastTwoSum(approxMedium, approxMin).
  1170. assert(-approxMedium >= Math.abs(approxMin));
  1171. fastTwoSumApproximation = approxMedium + approxMin;
  1172. bVirtual = fastTwoSumApproximation - approxMedium;
  1173. fastTwoSumRoundOff = approxMin - bVirtual;
  1174. double approxS1 = fastTwoSumApproximation;
  1175. double roundoffS1 = fastTwoSumRoundOff;
  1176.  
  1177. // Shewchuk/Dekker's FastTwoSum(approxMax, approxS1);
  1178. assert(approxMax >= Math.abs(approxS1));
  1179. fastTwoSumApproximation = approxMax + approxS1;
  1180. bVirtual = fastTwoSumApproximation - approxMax;
  1181. fastTwoSumRoundOff = approxS1 - bVirtual;
  1182. double roundoff1000 = fastTwoSumRoundOff;
  1183. double approx1000 = fastTwoSumApproximation;
  1184. double roundoffTotal = roundoffS1 + roundoff1000;
  1185.  
  1186. // Shewchuk/Dekker's FastTwoSum(approx1000, roundoffTotal);
  1187. assert(approx1000 >= Math.abs(roundoffTotal));
  1188. fastTwoSumApproximation = approx1000 + roundoffTotal;
  1189. bVirtual = fastTwoSumApproximation - approx1000;
  1190.  
  1191. // Now we have got the roundoff for the scaled fractional
  1192. double scaledFractionalRoundoff = roundoffTotal - bVirtual;
  1193.  
  1194. // ---- TwoProduct(fractionalPart, scale (i.e. 1000.0d or 100.0d)) end.
  1195.  
  1196. /* ---- Taking the rounding decision
  1197. *
  1198. * We take rounding decision based on roundoff and half-even rounding
  1199. * rule.
  1200. *
  1201. * The above TwoProduct gives us the exact roundoff on the approximated
  1202. * scaled fractional, and we know that this approximation is exactly
  1203. * 0.5d, since that has already been tested by the caller
  1204. * (fastDoubleFormat).
  1205. *
  1206. * Decision comes first from the sign of the calculated exact roundoff.
  1207. * - Since being exact roundoff, it cannot be positive with a scaled
  1208. * fractional less than 0.5d, as well as negative with a scaled
  1209. * fractional greater than 0.5d. That leaves us with following 3 cases.
  1210. * - positive, thus scaled fractional == 0.500....0fff ==> round-up.
  1211. * - negative, thus scaled fractional == 0.499....9fff ==> don't round-up.
  1212. * - is zero, thus scaled fractioanl == 0.5 ==> half-even rounding applies :
  1213. * we round-up only if the integral part of the scaled fractional is odd.
  1214. *
  1215. */
  1216. if (scaledFractionalRoundoff > 0.0) {
  1217. return true;
  1218. } else if (scaledFractionalRoundoff < 0.0) {
  1219. return false;
  1220. } else if ((scaledFractionalPartAsInt & 1) != 0) {
  1221. return true;
  1222. }
  1223.  
  1224. return false;
  1225.  
  1226. // ---- Taking the rounding decision end
  1227. }
  1228.  
  1229. /**
  1230. * Collects integral digits from passed {@code number}, while setting
  1231. * grouping chars as needed. Updates {@code firstUsedIndex} accordingly.
  1232. *
  1233. * Loops downward starting from {@code backwardIndex} position (inclusive).
  1234. *
  1235. * @param number The int value from which we collect digits.
  1236. * @param digitsBuffer The char array container where digits and grouping chars
  1237. * are stored.
  1238. * @param backwardIndex the position from which we start storing digits in
  1239. * digitsBuffer.
  1240. *
  1241. */
  1242. private void collectIntegralDigits(int number,
  1243. char[] digitsBuffer,
  1244. int backwardIndex) {
  1245. int index = backwardIndex;
  1246. int q;
  1247. int r;
  1248. while (number > 999) {
  1249. // Generates 3 digits per iteration.
  1250. q = number / 1000;
  1251. r = number - (q << 10) + (q << 4) + (q << 3); // -1024 +16 +8 = 1000.
  1252. number = q;
  1253.  
  1254. digitsBuffer[index--] = DigitArrays.DigitOnes1000[r];
  1255. digitsBuffer[index--] = DigitArrays.DigitTens1000[r];
  1256. digitsBuffer[index--] = DigitArrays.DigitHundreds1000[r];
  1257. digitsBuffer[index--] = fastPathData.groupingChar;
  1258. }
  1259.  
  1260. // Collects last 3 or less digits.
  1261. digitsBuffer[index] = DigitArrays.DigitOnes1000[number];
  1262. if (number > 9) {
  1263. digitsBuffer[--index] = DigitArrays.DigitTens1000[number];
  1264. if (number > 99)
  1265. digitsBuffer[--index] = DigitArrays.DigitHundreds1000[number];
  1266. }
  1267.  
  1268. fastPathData.firstUsedIndex = index;
  1269. }
  1270.  
  1271. /**
  1272. * Collects the 2 (currency) or 3 (decimal) fractional digits from passed
  1273. * {@code number}, starting at {@code startIndex} position
  1274. * inclusive. There is no punctuation to set here (no grouping chars).
  1275. * Updates {@code fastPathData.lastFreeIndex} accordingly.
  1276. *
  1277. *
  1278. * @param number The int value from which we collect digits.
  1279. * @param digitsBuffer The char array container where digits are stored.
  1280. * @param startIndex the position from which we start storing digits in
  1281. * digitsBuffer.
  1282. *
  1283. */
  1284. private void collectFractionalDigits(int number,
  1285. char[] digitsBuffer,
  1286. int startIndex) {
  1287. int index = startIndex;
  1288.  
  1289. char digitOnes = DigitArrays.DigitOnes1000[number];
  1290. char digitTens = DigitArrays.DigitTens1000[number];
  1291.  
  1292. if (isCurrencyFormat) {
  1293. // Currency case. Always collects fractional digits.
  1294. digitsBuffer[index++] = digitTens;
  1295. digitsBuffer[index++] = digitOnes;
  1296. } else if (number != 0) {
  1297. // Decimal case. Hundreds will always be collected
  1298. digitsBuffer[index++] = DigitArrays.DigitHundreds1000[number];
  1299.  
  1300. // Ending zeros won't be collected.
  1301. if (digitOnes != '0') {
  1302. digitsBuffer[index++] = digitTens;
  1303. digitsBuffer[index++] = digitOnes;
  1304. } else if (digitTens != '0')
  1305. digitsBuffer[index++] = digitTens;
  1306.  
  1307. } else
  1308. // This is decimal pattern and fractional part is zero.
  1309. // We must remove decimal point from result.
  1310. index--;
  1311.  
  1312. fastPathData.lastFreeIndex = index;
  1313. }
  1314.  
  1315. /**
  1316. * Internal utility.
  1317. * Adds the passed {@code prefix} and {@code suffix} to {@code container}.
  1318. *
  1319. * @param container Char array container which to prepend/append the
  1320. * prefix/suffix.
  1321. * @param prefix Char sequence to prepend as a prefix.
  1322. * @param suffix Char sequence to append as a suffix.
  1323. *
  1324. */
  1325. // private void addAffixes(boolean isNegative, char[] container) {
  1326. private void addAffixes(char[] container, char[] prefix, char[] suffix) {
  1327.  
  1328. // We add affixes only if needed (affix length > 0).
  1329. int pl = prefix.length;
  1330. int sl = suffix.length;
  1331. if (pl != 0) prependPrefix(prefix, pl, container);
  1332. if (sl != 0) appendSuffix(suffix, sl, container);
  1333.  
  1334. }
  1335.  
  1336. /**
  1337. * Prepends the passed {@code prefix} chars to given result
  1338. * {@code container}. Updates {@code fastPathData.firstUsedIndex}
  1339. * accordingly.
  1340. *
  1341. * @param prefix The prefix characters to prepend to result.
  1342. * @param len The number of chars to prepend.
  1343. * @param container Char array container which to prepend the prefix
  1344. */
  1345. private void prependPrefix(char[] prefix,
  1346. int len,
  1347. char[] container) {
  1348.  
  1349. fastPathData.firstUsedIndex -= len;
  1350. int startIndex = fastPathData.firstUsedIndex;
  1351.  
  1352. // If prefix to prepend is only 1 char long, just assigns this char.
  1353. // If prefix is less or equal 4, we use a dedicated algorithm that
  1354. // has shown to run faster than System.arraycopy.
  1355. // If more than 4, we use System.arraycopy.
  1356. if (len == 1)
  1357. container[startIndex] = prefix[0];
  1358. else if (len <= 4) {
  1359. int dstLower = startIndex;
  1360. int dstUpper = dstLower + len - 1;
  1361. int srcUpper = len - 1;
  1362. container[dstLower] = prefix[0];
  1363. container[dstUpper] = prefix[srcUpper];
  1364.  
  1365. if (len > 2)
  1366. container[++dstLower] = prefix[1];
  1367. if (len == 4)
  1368. container[--dstUpper] = prefix[2];
  1369. } else
  1370. System.arraycopy(prefix, 0, container, startIndex, len);
  1371. }
  1372.  
  1373. /**
  1374. * Appends the passed {@code suffix} chars to given result
  1375. * {@code container}. Updates {@code fastPathData.lastFreeIndex}
  1376. * accordingly.
  1377. *
  1378. * @param suffix The suffix characters to append to result.
  1379. * @param len The number of chars to append.
  1380. * @param container Char array container which to append the suffix
  1381. */
  1382. private void appendSuffix(char[] suffix,
  1383. int len,
  1384. char[] container) {
  1385.  
  1386. int startIndex = fastPathData.lastFreeIndex;
  1387.  
  1388. // If suffix to append is only 1 char long, just assigns this char.
  1389. // If suffix is less or equal 4, we use a dedicated algorithm that
  1390. // has shown to run faster than System.arraycopy.
  1391. // If more than 4, we use System.arraycopy.
  1392. if (len == 1)
  1393. container[startIndex] = suffix[0];
  1394. else if (len <= 4) {
  1395. int dstLower = startIndex;
  1396. int dstUpper = dstLower + len - 1;
  1397. int srcUpper = len - 1;
  1398. container[dstLower] = suffix[0];
  1399. container[dstUpper] = suffix[srcUpper];
  1400.  
  1401. if (len > 2)
  1402. container[++dstLower] = suffix[1];
  1403. if (len == 4)
  1404. container[--dstUpper] = suffix[2];
  1405. } else
  1406. System.arraycopy(suffix, 0, container, startIndex, len);
  1407.  
  1408. fastPathData.lastFreeIndex += len;
  1409. }
  1410.  
  1411. /**
  1412. * Converts digit chars from {@code digitsBuffer} to current locale.
  1413. *
  1414. * Must be called before adding affixes since we refer to
  1415. * {@code fastPathData.firstUsedIndex} and {@code fastPathData.lastFreeIndex},
  1416. * and do not support affixes (for speed reason).
  1417. *
  1418. * We loop backward starting from last used index in {@code fastPathData}.
  1419. *
  1420. * @param digitsBuffer The char array container where the digits are stored.
  1421. */
  1422. private void localizeDigits(char[] digitsBuffer) {
  1423.  
  1424. // We will localize only the digits, using the groupingSize,
  1425. // and taking into account fractional part.
  1426.  
  1427. // First take into account fractional part.
  1428. int digitsCounter =
  1429. fastPathData.lastFreeIndex - fastPathData.fractionalFirstIndex;
  1430.  
  1431. // The case when there is no fractional digits.
  1432. if (digitsCounter < 0)
  1433. digitsCounter = groupingSize;
  1434.  
  1435. // Only the digits remains to localize.
  1436. for (int cursor = fastPathData.lastFreeIndex - 1;
  1437. cursor >= fastPathData.firstUsedIndex;
  1438. cursor--) {
  1439. if (digitsCounter != 0) {
  1440. // This is a digit char, we must localize it.
  1441. digitsBuffer[cursor] += fastPathData.zeroDelta;
  1442. digitsCounter--;
  1443. } else {
  1444. // Decimal separator or grouping char. Reinit counter only.
  1445. digitsCounter = groupingSize;
  1446. }
  1447. }
  1448. }
  1449.  
  1450. /**
  1451. * This is the main entry point for the fast-path format algorithm.
  1452. *
  1453. * At this point we are sure to be in the expected conditions to run it.
  1454. * This algorithm builds the formatted result and puts it in the dedicated
  1455. * {@code fastPathData.fastPathContainer}.
  1456. *
  1457. * @param d the double value to be formatted.
  1458. * @param negative Flag precising if {@code d} is negative.
  1459. */
  1460. private void fastDoubleFormat(double d,
  1461. boolean negative) {
  1462.  
  1463. char[] container = fastPathData.fastPathContainer;
  1464.  
  1465. /*
  1466. * The principle of the algorithm is to :
  1467. * - Break the passed double into its integral and fractional parts
  1468. * converted into integers.
  1469. * - Then decide if rounding up must be applied or not by following
  1470. * the half-even rounding rule, first using approximated scaled
  1471. * fractional part.
  1472. * - For the difficult cases (approximated scaled fractional part
  1473. * being exactly 0.5d), we refine the rounding decision by calling
  1474. * exactRoundUp utility method that both calculates the exact roundoff
  1475. * on the approximation and takes correct rounding decision.
  1476. * - We round-up the fractional part if needed, possibly propagating the
  1477. * rounding to integral part if we meet a "all-nine" case for the
  1478. * scaled fractional part.
  1479. * - We then collect digits from the resulting integral and fractional
  1480. * parts, also setting the required grouping chars on the fly.
  1481. * - Then we localize the collected digits if needed, and
  1482. * - Finally prepend/append prefix/suffix if any is needed.
  1483. */
  1484.  
  1485. // Exact integral part of d.
  1486. int integralPartAsInt = (int) d;
  1487.  
  1488. // Exact fractional part of d (since we subtract it's integral part).
  1489. double exactFractionalPart = d - (double) integralPartAsInt;
  1490.  
  1491. // Approximated scaled fractional part of d (due to multiplication).
  1492. double scaledFractional =
  1493. exactFractionalPart * fastPathData.fractionalScaleFactor;
  1494.  
  1495. // Exact integral part of scaled fractional above.
  1496. int fractionalPartAsInt = (int) scaledFractional;
  1497.  
  1498. // Exact fractional part of scaled fractional above.
  1499. scaledFractional = scaledFractional - (double) fractionalPartAsInt;
  1500.  
  1501. // Only when scaledFractional is exactly 0.5d do we have to do exact
  1502. // calculations and take fine-grained rounding decision, since
  1503. // approximated results above may lead to incorrect decision.
  1504. // Otherwise comparing against 0.5d (strictly greater or less) is ok.
  1505. boolean roundItUp = false;
  1506. if (scaledFractional >= 0.5d) {
  1507. if (scaledFractional == 0.5d)
  1508. // Rounding need fine-grained decision.
  1509. roundItUp = exactRoundUp(exactFractionalPart, fractionalPartAsInt);
  1510. else
  1511. roundItUp = true;
  1512.  
  1513. if (roundItUp) {
  1514. // Rounds up both fractional part (and also integral if needed).
  1515. if (fractionalPartAsInt < fastPathData.fractionalMaxIntBound) {
  1516. fractionalPartAsInt++;
  1517. } else {
  1518. // Propagates rounding to integral part since "all nines" case.
  1519. fractionalPartAsInt = 0;
  1520. integralPartAsInt++;
  1521. }
  1522. }
  1523. }
  1524.  
  1525. // Collecting digits.
  1526. collectFractionalDigits(fractionalPartAsInt, container,
  1527. fastPathData.fractionalFirstIndex);
  1528. collectIntegralDigits(integralPartAsInt, container,
  1529. fastPathData.integralLastIndex);
  1530.  
  1531. // Localizing digits.
  1532. if (fastPathData.zeroDelta != 0)
  1533. localizeDigits(container);
  1534.  
  1535. // Adding prefix and suffix.
  1536. if (negative) {
  1537. if (fastPathData.negativeAffixesRequired)
  1538. addAffixes(container,
  1539. fastPathData.charsNegativePrefix,
  1540. fastPathData.charsNegativeSuffix);
  1541. } else if (fastPathData.positiveAffixesRequired)
  1542. addAffixes(container,
  1543. fastPathData.charsPositivePrefix,
  1544. fastPathData.charsPositiveSuffix);
  1545. }
  1546.  
  1547. /**
  1548. * A fast-path shortcut of format(double) to be called by NumberFormat, or by
  1549. * format(double, ...) public methods.
  1550. *
  1551. * If instance can be applied fast-path and passed double is not NaN or
  1552. * Infinity, is in the integer range, we call {@code fastDoubleFormat}
  1553. * after changing {@code d} to its positive value if necessary.
  1554. *
  1555. * Otherwise returns null by convention since fast-path can't be exercized.
  1556. *
  1557. * @param d The double value to be formatted
  1558. *
  1559. * @return the formatted result for {@code d} as a string.
  1560. */
  1561. String fastFormat(double d) {
  1562. boolean isDataSet = false;
  1563. // (Re-)Evaluates fast-path status if needed.
  1564. if (fastPathCheckNeeded) {
  1565. isDataSet = checkAndSetFastPathStatus();
  1566. }
  1567.  
  1568. if (!isFastPath )
  1569. // DecimalFormat instance is not in a fast-path state.
  1570. return null;
  1571.  
  1572. if (!Double.isFinite(d))
  1573. // Should not use fast-path for Infinity and NaN.
  1574. return null;
  1575.  
  1576. // Extracts and records sign of double value, possibly changing it
  1577. // to a positive one, before calling fastDoubleFormat().
  1578. boolean negative = false;
  1579. if (d < 0.0d) {
  1580. negative = true;
  1581. d = -d;
  1582. } else if (d == 0.0d) {
  1583. negative = (Math.copySign(1.0d, d) == -1.0d);
  1584. d = +0.0d;
  1585. }
  1586.  
  1587. if (d > MAX_INT_AS_DOUBLE)
  1588. // Filters out values that are outside expected fast-path range
  1589. return null;
  1590. else {
  1591. if (!isDataSet) {
  1592. /*
  1593. * If the fast path data is not set through
  1594. * checkAndSetFastPathStatus() and fulfil the
  1595. * fast path conditions then reset the data
  1596. * directly through resetFastPathData()
  1597. */
  1598. resetFastPathData(isFastPath);
  1599. }
  1600. fastDoubleFormat(d, negative);
  1601.  
  1602. }
  1603.  
  1604. // Returns a new string from updated fastPathContainer.
  1605. return new String(fastPathData.fastPathContainer,
  1606. fastPathData.firstUsedIndex,
  1607. fastPathData.lastFreeIndex - fastPathData.firstUsedIndex);
  1608.  
  1609. }
  1610.  
  1611. // ======== End fast-path formating logic for double =========================
  1612.  
  1613. /**
  1614. * Complete the formatting of a finite number. On entry, the digitList must
  1615. * be filled in with the correct digits.
  1616. */
  1617. private StringBuffer subformat(StringBuffer result, FieldDelegate delegate,
  1618. boolean isNegative, boolean isInteger,
  1619. int maxIntDigits, int minIntDigits,
  1620. int maxFraDigits, int minFraDigits) {
  1621. // NOTE: This isn't required anymore because DigitList takes care of this.
  1622. //
  1623. // // The negative of the exponent represents the number of leading
  1624. // // zeros between the decimal and the first non-zero digit, for
  1625. // // a value < 0.1 (e.g., for 0.00123, -fExponent == 2). If this
  1626. // // is more than the maximum fraction digits, then we have an underflow
  1627. // // for the printed representation. We recognize this here and set
  1628. // // the DigitList representation to zero in this situation.
  1629. //
  1630. // if (-digitList.decimalAt >= getMaximumFractionDigits())
  1631. // {
  1632. // digitList.count = 0;
  1633. // }
  1634.  
  1635. char zero = symbols.getZeroDigit();
  1636. int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero
  1637. char grouping = symbols.getGroupingSeparator();
  1638. char decimal = isCurrencyFormat ?
  1639. symbols.getMonetaryDecimalSeparator() :
  1640. symbols.getDecimalSeparator();
  1641.  
  1642. /* Per bug 4147706, DecimalFormat must respect the sign of numbers which
  1643. * format as zero. This allows sensible computations and preserves
  1644. * relations such as signum(1/x) = signum(x), where x is +Infinity or
  1645. * -Infinity. Prior to this fix, we always formatted zero values as if
  1646. * they were positive. Liu 7/6/98.
  1647. */
  1648. if (digitList.isZero()) {
  1649. digitList.decimalAt = 0; // Normalize
  1650. }
  1651.  
  1652. if (isNegative) {
  1653. append(result, negativePrefix, delegate,
  1654. getNegativePrefixFieldPositions(), Field.SIGN);
  1655. } else {
  1656. append(result, positivePrefix, delegate,
  1657. getPositivePrefixFieldPositions(), Field.SIGN);
  1658. }
  1659.  
  1660. if (useExponentialNotation) {
  1661. int iFieldStart = result.length();
  1662. int iFieldEnd = -1;
  1663. int fFieldStart = -1;
  1664.  
  1665. // Minimum integer digits are handled in exponential format by
  1666. // adjusting the exponent. For example, 0.01234 with 3 minimum
  1667. // integer digits is "123.4E-4".
  1668.  
  1669. // Maximum integer digits are interpreted as indicating the
  1670. // repeating range. This is useful for engineering notation, in
  1671. // which the exponent is restricted to a multiple of 3. For
  1672. // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
  1673. // If maximum integer digits are > 1 and are larger than
  1674. // minimum integer digits, then minimum integer digits are
  1675. // ignored.
  1676. int exponent = digitList.decimalAt;
  1677. int repeat = maxIntDigits;
  1678. int minimumIntegerDigits = minIntDigits;
  1679. if (repeat > 1 && repeat > minIntDigits) {
  1680. // A repeating range is defined; adjust to it as follows.
  1681. // If repeat == 3, we have 6,5,4=>3; 3,2,1=>0; 0,-1,-2=>-3;
  1682. // -3,-4,-5=>-6, etc. This takes into account that the
  1683. // exponent we have here is off by one from what we expect;
  1684. // it is for the format 0.MMMMMx10^n.
  1685. if (exponent >= 1) {
  1686. exponent = ((exponent - 1) / repeat) * repeat;
  1687. } else {
  1688. // integer division rounds towards 0
  1689. exponent = ((exponent - repeat) / repeat) * repeat;
  1690. }
  1691. minimumIntegerDigits = 1;
  1692. } else {
  1693. // No repeating range is defined; use minimum integer digits.
  1694. exponent -= minimumIntegerDigits;
  1695. }
  1696.  
  1697. // We now output a minimum number of digits, and more if there
  1698. // are more digits, up to the maximum number of digits. We
  1699. // place the decimal point after the "integer" digits, which
  1700. // are the first (decimalAt - exponent) digits.
  1701. int minimumDigits = minIntDigits + minFraDigits;
  1702. if (minimumDigits < 0) { // overflow?
  1703. minimumDigits = Integer.MAX_VALUE;
  1704. }
  1705.  
  1706. // The number of integer digits is handled specially if the number
  1707. // is zero, since then there may be no digits.
  1708. int integerDigits = digitList.isZero() ? minimumIntegerDigits :
  1709. digitList.decimalAt - exponent;
  1710. if (minimumDigits < integerDigits) {
  1711. minimumDigits = integerDigits;
  1712. }
  1713. int totalDigits = digitList.count;
  1714. if (minimumDigits > totalDigits) {
  1715. totalDigits = minimumDigits;
  1716. }
  1717. boolean addedDecimalSeparator = false;
  1718.  
  1719. for (int i=0; i<totalDigits; ++i) {
  1720. if (i == integerDigits) {
  1721. // Record field information for caller.
  1722. iFieldEnd = result.length();
  1723.  
  1724. result.append(decimal);
  1725. addedDecimalSeparator = true;
  1726.  
  1727. // Record field information for caller.
  1728. fFieldStart = result.length();
  1729. }
  1730. result.append((i < digitList.count) ?
  1731. (char)(digitList.digits[i] + zeroDelta) :
  1732. zero);
  1733. }
  1734.  
  1735. if (decimalSeparatorAlwaysShown && totalDigits == integerDigits) {
  1736. // Record field information for caller.
  1737. iFieldEnd = result.length();
  1738.  
  1739. result.append(decimal);
  1740. addedDecimalSeparator = true;
  1741.  
  1742. // Record field information for caller.
  1743. fFieldStart = result.length();
  1744. }
  1745.  
  1746. // Record field information
  1747. if (iFieldEnd == -1) {
  1748. iFieldEnd = result.length();
  1749. }
  1750. delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
  1751. iFieldStart, iFieldEnd, result);
  1752. if (addedDecimalSeparator) {
  1753. delegate.formatted(Field.DECIMAL_SEPARATOR,
  1754. Field.DECIMAL_SEPARATOR,
  1755. iFieldEnd, fFieldStart, result);
  1756. }
  1757. if (fFieldStart == -1) {
  1758. fFieldStart = result.length();
  1759. }
  1760. delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION,
  1761. fFieldStart, result.length(), result);
  1762.  
  1763. // The exponent is output using the pattern-specified minimum
  1764. // exponent digits. There is no maximum limit to the exponent
  1765. // digits, since truncating the exponent would result in an
  1766. // unacceptable inaccuracy.
  1767. int fieldStart = result.length();
  1768.  
  1769. result.append(symbols.getExponentSeparator());
  1770.  
  1771. delegate.formatted(Field.EXPONENT_SYMBOL, Field.EXPONENT_SYMBOL,
  1772. fieldStart, result.length(), result);
  1773.  
  1774. // For zero values, we force the exponent to zero. We
  1775. // must do this here, and not earlier, because the value
  1776. // is used to determine integer digit count above.
  1777. if (digitList.isZero()) {
  1778. exponent = 0;
  1779. }
  1780.  
  1781. boolean negativeExponent = exponent < 0;
  1782. if (negativeExponent) {
  1783. exponent = -exponent;
  1784. fieldStart = result.length();
  1785. result.append(symbols.getMinusSign());
  1786. delegate.formatted(Field.EXPONENT_SIGN, Field.EXPONENT_SIGN,
  1787. fieldStart, result.length(), result);
  1788. }
  1789. digitList.set(negativeExponent, exponent);
  1790.  
  1791. int eFieldStart = result.length();
  1792.  
  1793. for (int i=digitList.decimalAt; i<minExponentDigits; ++i) {
  1794. result.append(zero);
  1795. }
  1796. for (int i=0; i<digitList.decimalAt; ++i) {
  1797. result.append((i < digitList.count) ?
  1798. (char)(digitList.digits[i] + zeroDelta) : zero);
  1799. }
  1800. delegate.formatted(Field.EXPONENT, Field.EXPONENT, eFieldStart,
  1801. result.length(), result);
  1802. } else {
  1803. int iFieldStart = result.length();
  1804.  
  1805. // Output the integer portion. Here 'count' is the total
  1806. // number of integer digits we will display, including both
  1807. // leading zeros required to satisfy getMinimumIntegerDigits,
  1808. // and actual digits present in the number.
  1809. int count = minIntDigits;
  1810. int digitIndex = 0; // Index into digitList.fDigits[]
  1811. if (digitList.decimalAt > 0 && count < digitList.decimalAt) {
  1812. count = digitList.decimalAt;
  1813. }
  1814.  
  1815. // Handle the case where getMaximumIntegerDigits() is smaller
  1816. // than the real number of integer digits. If this is so, we
  1817. // output the least significant max integer digits. For example,
  1818. // the value 1997 printed with 2 max integer digits is just "97".
  1819. if (count > maxIntDigits) {
  1820. count = maxIntDigits;
  1821. digitIndex = digitList.decimalAt - count;
  1822. }
  1823.  
  1824. int sizeBeforeIntegerPart = result.length();
  1825. for (int i=count-1; i>=0; --i) {
  1826. if (i < digitList.decimalAt && digitIndex < digitList.count) {
  1827. // Output a real digit
  1828. result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
  1829. } else {
  1830. // Output a leading zero
  1831. result.append(zero);
  1832. }
  1833.  
  1834. // Output grouping separator if necessary. Don't output a
  1835. // grouping separator if i==0 though; that's at the end of
  1836. // the integer part.
  1837. if (isGroupingUsed() && i>0 && (groupingSize != 0) &&
  1838. (i % groupingSize == 0)) {
  1839. int gStart = result.length();
  1840. result.append(grouping);
  1841. delegate.formatted(Field.GROUPING_SEPARATOR,
  1842. Field.GROUPING_SEPARATOR, gStart,
  1843. result.length(), result);
  1844. }
  1845. }
  1846.  
  1847. // Determine whether or not there are any printable fractional
  1848. // digits. If we've used up the digits we know there aren't.
  1849. boolean fractionPresent = (minFraDigits > 0) ||
  1850. (!isInteger && digitIndex < digitList.count);
  1851.  
  1852. // If there is no fraction present, and we haven't printed any
  1853. // integer digits, then print a zero. Otherwise we won't print
  1854. // _any_ digits, and we won't be able to parse this string.
  1855. if (!fractionPresent && result.length() == sizeBeforeIntegerPart) {
  1856. result.append(zero);
  1857. }
  1858.  
  1859. delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
  1860. iFieldStart, result.length(), result);
  1861.  
  1862. // Output the decimal separator if we always do so.
  1863. int sStart = result.length();
  1864. if (decimalSeparatorAlwaysShown || fractionPresent) {
  1865. result.append(decimal);
  1866. }
  1867.  
  1868. if (sStart != result.length()) {
  1869. delegate.formatted(Field.DECIMAL_SEPARATOR,
  1870. Field.DECIMAL_SEPARATOR,
  1871. sStart, result.length(), result);
  1872. }
  1873. int fFieldStart = result.length();
  1874.  
  1875. for (int i=0; i < maxFraDigits; ++i) {
  1876. // Here is where we escape from the loop. We escape if we've
  1877. // output the maximum fraction digits (specified in the for
  1878. // expression above).
  1879. // We also stop when we've output the minimum digits and either:
  1880. // we have an integer, so there is no fractional stuff to
  1881. // display, or we're out of significant digits.
  1882. if (i >= minFraDigits &&
  1883. (isInteger || digitIndex >= digitList.count)) {
  1884. break;
  1885. }
  1886.  
  1887. // Output leading fractional zeros. These are zeros that come
  1888. // after the decimal but before any significant digits. These
  1889. // are only output if abs(number being formatted) < 1.0.
  1890. if (-1-i > (digitList.decimalAt-1)) {
  1891. result.append(zero);
  1892. continue;
  1893. }
  1894.  
  1895. // Output a digit, if we have any precision left, or a
  1896. // zero if we don't. We don't want to output noise digits.
  1897. if (!isInteger && digitIndex < digitList.count) {
  1898. result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
  1899. } else {
  1900. result.append(zero);
  1901. }
  1902. }
  1903.  
  1904. // Record field information for caller.
  1905. delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION,
  1906. fFieldStart, result.length(), result);
  1907. }
  1908.  
  1909. if (isNegative) {
  1910. append(result, negativeSuffix, delegate,
  1911. getNegativeSuffixFieldPositions(), Field.SIGN);
  1912. } else {
  1913. append(result, positiveSuffix, delegate,
  1914. getPositiveSuffixFieldPositions(), Field.SIGN);
  1915. }
  1916.  
  1917. return result;
  1918. }
  1919.  
  1920. /**
  1921. * Appends the String <code>string</code> to <code>result</code>.
  1922. * <code>delegate</code> is notified of all the
  1923. * <code>FieldPosition</code>s in <code>positions</code>.
  1924. * <p>
  1925. * If one of the <code>FieldPosition</code>s in <code>positions</code>
  1926. * identifies a <code>SIGN</code> attribute, it is mapped to
  1927. * <code>signAttribute</code>. This is used
  1928. * to map the <code>SIGN</code> attribute to the <code>EXPONENT</code>
  1929. * attribute as necessary.
  1930. * <p>
  1931. * This is used by <code>subformat</code> to add the prefix/suffix.
  1932. */
  1933. private void append(StringBuffer result, String string,
  1934. FieldDelegate delegate,
  1935. FieldPosition[] positions,
  1936. Format.Field signAttribute) {
  1937. int start = result.length();
  1938.  
  1939. if (string.length() > 0) {
  1940. result.append(string);
  1941. for (int counter = 0, max = positions.length; counter < max;
  1942. counter++) {
  1943. FieldPosition fp = positions[counter];
  1944. Format.Field attribute = fp.getFieldAttribute();
  1945.  
  1946. if (attribute == Field.SIGN) {
  1947. attribute = signAttribute;
  1948. }
  1949. delegate.formatted(attribute, attribute,
  1950. start + fp.getBeginIndex(),
  1951. start + fp.getEndIndex(), result);
  1952. }
  1953. }
  1954. }
  1955.  
  1956. /**
  1957. * Parses text from a string to produce a <code>Number</code>.
  1958. * <p>
  1959. * The method attempts to parse text starting at the index given by
  1960. * <code>pos</code>.
  1961. * If parsing succeeds, then the index of <code>pos</code> is updated
  1962. * to the index after the last character used (parsing does not necessarily
  1963. * use all characters up to the end of the string), and the parsed
  1964. * number is returned. The updated <code>pos</code> can be used to
  1965. * indicate the starting point for the next call to this method.
  1966. * If an error occurs, then the index of <code>pos</code> is not
  1967. * changed, the error index of <code>pos</code> is set to the index of
  1968. * the character where the error occurred, and null is returned.
  1969. * <p>
  1970. * The subclass returned depends on the value of {@link #isParseBigDecimal}
  1971. * as well as on the string being parsed.
  1972. * <ul>
  1973. * <li>If <code>isParseBigDecimal()</code> is false (the default),
  1974. * most integer values are returned as <code>Long</code>
  1975. * objects, no matter how they are written: <code>"17"</code> and
  1976. * <code>"17.000"</code> both parse to <code>Long(17)</code>.
  1977. * Values that cannot fit into a <code>Long</code> are returned as
  1978. * <code>Double</code>s. This includes values with a fractional part,
  1979. * infinite values, <code>NaN</code>, and the value -0.0.
  1980. * <code>DecimalFormat</code> does <em>not</em> decide whether to
  1981. * return a <code>Double</code> or a <code>Long</code> based on the
  1982. * presence of a decimal separator in the source string. Doing so
  1983. * would prevent integers that overflow the mantissa of a double,
  1984. * such as <code>"-9,223,372,036,854,775,808.00"</code>, from being
  1985. * parsed accurately.
  1986. * <p>
  1987. * Callers may use the <code>Number</code> methods
  1988. * <code>doubleValue</code>, <code>longValue</code>, etc., to obtain
  1989. * the type they want.
  1990. * <li>If <code>isParseBigDecimal()</code> is true, values are returned
  1991. * as <code>BigDecimal</code> objects. The values are the ones
  1992. * constructed by {@link java.math.BigDecimal#BigDecimal(String)}
  1993. * for corresponding strings in locale-independent format. The
  1994. * special cases negative and positive infinity and NaN are returned
  1995. * as <code>Double</code> instances holding the values of the
  1996. * corresponding <code>Double</code> constants.
  1997. * </ul>
  1998. * <p>
  1999. * <code>DecimalFormat</code> parses all Unicode characters that represent
  2000. * decimal digits, as defined by <code>Character.digit()</code>. In
  2001. * addition, <code>DecimalFormat</code> also recognizes as digits the ten
  2002. * consecutive characters starting with the localized zero digit defined in
  2003. * the <code>DecimalFormatSymbols</code> object.
  2004. *
  2005. * @param text the string to be parsed
  2006. * @param pos A <code>ParsePosition</code> object with index and error
  2007. * index information as described above.
  2008. * @return the parsed value, or <code>null</code> if the parse fails
  2009. * @exception NullPointerException if <code>text</code> or
  2010. * <code>pos</code> is null.
  2011. */
  2012. @Override
  2013. public Number parse(String text, ParsePosition pos) {
  2014. // special case NaN
  2015. if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols.getNaN().length())) {
  2016. pos.index = pos.index + symbols.getNaN().length();
  2017. return Double.valueOf(Double.NaN);
  2018. }
  2019.  
  2020. boolean[] status = new boolean[STATUS_LENGTH];
  2021. if (!subparse(text, pos, positivePrefix, negativePrefix, digitList, false, status)) {
  2022. return null;
  2023. }
  2024.  
  2025. // special case INFINITY
  2026. if (status[STATUS_INFINITE]) {
  2027. if (status[STATUS_POSITIVE] == (multiplier >= 0)) {
  2028. return Double.valueOf(Double.POSITIVE_INFINITY);
  2029. } else {
  2030. return Double.valueOf(Double.NEGATIVE_INFINITY);
  2031. }
  2032. }
  2033.  
  2034. if (multiplier == 0) {
  2035. if (digitList.isZero()) {
  2036. return Double.valueOf(Double.NaN);
  2037. } else if (status[STATUS_POSITIVE]) {
  2038. return Double.valueOf(Double.POSITIVE_INFINITY);
  2039. } else {
  2040. return Double.valueOf(Double.NEGATIVE_INFINITY);
  2041. }
  2042. }
  2043.  
  2044. if (isParseBigDecimal()) {
  2045. BigDecimal bigDecimalResult = digitList.getBigDecimal();
  2046.  
  2047. if (multiplier != 1) {
  2048. try {
  2049. bigDecimalResult = bigDecimalResult.divide(getBigDecimalMultiplier());
  2050. }
  2051. catch (ArithmeticException e) { // non-terminating decimal expansion
  2052. bigDecimalResult = bigDecimalResult.divide(getBigDecimalMultiplier(), roundingMode);
  2053. }
  2054. }
  2055.  
  2056. if (!status[STATUS_POSITIVE]) {
  2057. bigDecimalResult = bigDecimalResult.negate();
  2058. }
  2059. return bigDecimalResult;
  2060. } else {
  2061. boolean gotDouble = true;
  2062. boolean gotLongMinimum = false;
  2063. double doubleResult = 0.0;
  2064. long longResult = 0;
  2065.  
  2066. // Finally, have DigitList parse the digits into a value.
  2067. if (digitList.fitsIntoLong(status[STATUS_POSITIVE], isParseIntegerOnly())) {
  2068. gotDouble = false;
  2069. longResult = digitList.getLong();
  2070. if (longResult < 0) { // got Long.MIN_VALUE
  2071. gotLongMinimum = true;
  2072. }
  2073. } else {
  2074. doubleResult = digitList.getDouble();
  2075. }
  2076.  
  2077. // Divide by multiplier. We have to be careful here not to do
  2078. // unneeded conversions between double and long.
  2079. if (multiplier != 1) {
  2080. if (gotDouble) {
  2081. doubleResult /= multiplier;
  2082. } else {
  2083. // Avoid converting to double if we can
  2084. if (longResult % multiplier == 0) {
  2085. longResult /= multiplier;
  2086. } else {
  2087. doubleResult = ((double)longResult) / multiplier;
  2088. gotDouble = true;
  2089. }
  2090. }
  2091. }
  2092.  
  2093. if (!status[STATUS_POSITIVE] && !gotLongMinimum) {
  2094. doubleResult = -doubleResult;
  2095. longResult = -longResult;
  2096. }
  2097.  
  2098. // At this point, if we divided the result by the multiplier, the
  2099. // result may fit into a long. We check for this case and return
  2100. // a long if possible.
  2101. // We must do this AFTER applying the negative (if appropriate)
  2102. // in order to handle the case of LONG_MIN; otherwise, if we do
  2103. // this with a positive value -LONG_MIN, the double is > 0, but
  2104. // the long is < 0. We also must retain a double in the case of
  2105. // -0.0, which will compare as == to a long 0 cast to a double
  2106. // (bug 4162852).
  2107. if (multiplier != 1 && gotDouble) {
  2108. longResult = (long)doubleResult;
  2109. gotDouble = ((doubleResult != (double)longResult) ||
  2110. (doubleResult == 0.0 && 1/doubleResult < 0.0)) &&
  2111. !isParseIntegerOnly();
  2112. }
  2113.  
  2114. // cast inside of ?: because of binary numeric promotion, JLS 15.25
  2115. return gotDouble ? (Number)doubleResult : (Number)longResult;
  2116. }
  2117. }
  2118.  
  2119. /**
  2120. * Return a BigInteger multiplier.
  2121. */
  2122. private BigInteger getBigIntegerMultiplier() {
  2123. if (bigIntegerMultiplier == null) {
  2124. bigIntegerMultiplier = BigInteger.valueOf(multiplier);
  2125. }
  2126. return bigIntegerMultiplier;
  2127. }
  2128. private transient BigInteger bigIntegerMultiplier;
  2129.  
  2130. /**
  2131. * Return a BigDecimal multiplier.
  2132. */
  2133. private BigDecimal getBigDecimalMultiplier() {
  2134. if (bigDecimalMultiplier == null) {
  2135. bigDecimalMultiplier = new BigDecimal(multiplier);
  2136. }
  2137. return bigDecimalMultiplier;
  2138. }
  2139. private transient BigDecimal bigDecimalMultiplier;
  2140.  
  2141. private static final int STATUS_INFINITE = 0;
  2142. private static final int STATUS_POSITIVE = 1;
  2143. private static final int STATUS_LENGTH = 2;
  2144.  
  2145. /**
  2146. * Parse the given text into a number. The text is parsed beginning at
  2147. * parsePosition, until an unparseable character is seen.
  2148. * @param text The string to parse.
  2149. * @param parsePosition The position at which to being parsing. Upon
  2150. * return, the first unparseable character.
  2151. * @param digits The DigitList to set to the parsed value.
  2152. * @param isExponent If true, parse an exponent. This means no
  2153. * infinite values and integer only.
  2154. * @param status Upon return contains boolean status flags indicating
  2155. * whether the value was infinite and whether it was positive.
  2156. */
  2157. private final boolean subparse(String text, ParsePosition parsePosition,
  2158. String positivePrefix, String negativePrefix,
  2159. DigitList digits, boolean isExponent,
  2160. boolean status[]) {
  2161. int position = parsePosition.index;
  2162. int oldStart = parsePosition.index;
  2163. int backup;
  2164. boolean gotPositive, gotNegative;
  2165.  
  2166. // check for positivePrefix; take longest
  2167. gotPositive = text.regionMatches(position, positivePrefix, 0,
  2168. positivePrefix.length());
  2169. gotNegative = text.regionMatches(position, negativePrefix, 0,
  2170. negativePrefix.length());
  2171.  
  2172. if (gotPositive && gotNegative) {
  2173. if (positivePrefix.length() > negativePrefix.length()) {
  2174. gotNegative = false;
  2175. } else if (positivePrefix.length() < negativePrefix.length()) {
  2176. gotPositive = false;
  2177. }
  2178. }
  2179.  
  2180. if (gotPositive) {
  2181. position += positivePrefix.length();
  2182. } else if (gotNegative) {
  2183. position += negativePrefix.length();
  2184. } else {
  2185. parsePosition.errorIndex = position;
  2186. return false;
  2187. }
  2188.  
  2189. // process digits or Inf, find decimal position
  2190. status[STATUS_INFINITE] = false;
  2191. if (!isExponent && text.regionMatches(position,symbols.getInfinity(),0,
  2192. symbols.getInfinity().length())) {
  2193. position += symbols.getInfinity().length();
  2194. status[STATUS_INFINITE] = true;
  2195. } else {
  2196. // We now have a string of digits, possibly with grouping symbols,
  2197. // and decimal points. We want to process these into a DigitList.
  2198. // We don't want to put a bunch of leading zeros into the DigitList
  2199. // though, so we keep track of the location of the decimal point,
  2200. // put only significant digits into the DigitList, and adjust the
  2201. // exponent as needed.
  2202.  
  2203. digits.decimalAt = digits.count = 0;
  2204. char zero = symbols.getZeroDigit();
  2205. char decimal = isCurrencyFormat ?
  2206. symbols.getMonetaryDecimalSeparator() :
  2207. symbols.getDecimalSeparator();
  2208. char grouping = symbols.getGroupingSeparator();
  2209. String exponentString = symbols.getExponentSeparator();
  2210. boolean sawDecimal = false;
  2211. boolean sawExponent = false;
  2212. boolean sawDigit = false;
  2213. int exponent = 0; // Set to the exponent value, if any
  2214.  
  2215. // We have to track digitCount ourselves, because digits.count will
  2216. // pin when the maximum allowable digits is reached.
  2217. int digitCount = 0;
  2218.  
  2219. backup = -1;
  2220. for (; position < text.length(); ++position) {
  2221. char ch = text.charAt(position);
  2222.  
  2223. /* We recognize all digit ranges, not only the Latin digit range
  2224. * '0'..'9'. We do so by using the Character.digit() method,
  2225. * which converts a valid Unicode digit to the range 0..9.
  2226. *
  2227. * The character 'ch' may be a digit. If so, place its value
  2228. * from 0 to 9 in 'digit'. First try using the locale digit,
  2229. * which may or MAY NOT be a standard Unicode digit range. If
  2230. * this fails, try using the standard Unicode digit ranges by
  2231. * calling Character.digit(). If this also fails, digit will
  2232. * have a value outside the range 0..9.
  2233. */
  2234. int digit = ch - zero;
  2235. if (digit < 0 || digit > 9) {
  2236. digit = Character.digit(ch, 10);
  2237. }
  2238.  
  2239. if (digit == 0) {
  2240. // Cancel out backup setting (see grouping handler below)
  2241. backup = -1; // Do this BEFORE continue statement below!!!
  2242. sawDigit = true;
  2243.  
  2244. // Handle leading zeros
  2245. if (digits.count == 0) {
  2246. // Ignore leading zeros in integer part of number.
  2247. if (!sawDecimal) {
  2248. continue;
  2249. }
  2250.  
  2251. // If we have seen the decimal, but no significant
  2252. // digits yet, then we account for leading zeros by
  2253. // decrementing the digits.decimalAt into negative
  2254. // values.
  2255. --digits.decimalAt;
  2256. } else {
  2257. ++digitCount;
  2258. digits.append((char)(digit + '0'));
  2259. }
  2260. } else if (digit > 0 && digit <= 9) { // [sic] digit==0 handled above
  2261. sawDigit = true;
  2262. ++digitCount;
  2263. digits.append((char)(digit + '0'));
  2264.  
  2265. // Cancel out backup setting (see grouping handler below)
  2266. backup = -1;
  2267. } else if (!isExponent && ch == decimal) {
  2268. // If we're only parsing integers, or if we ALREADY saw the
  2269. // decimal, then don't parse this one.
  2270. if (isParseIntegerOnly() || sawDecimal) {
  2271. break;
  2272. }
  2273. digits.decimalAt = digitCount; // Not digits.count!
  2274. sawDecimal = true;
  2275. } else if (!isExponent && ch == grouping && isGroupingUsed()) {
  2276. if (sawDecimal) {
  2277. break;
  2278. }
  2279. // Ignore grouping characters, if we are using them, but
  2280. // require that they be followed by a digit. Otherwise
  2281. // we backup and reprocess them.
  2282. backup = position;
  2283. } else if (!isExponent && text.regionMatches(position, exponentString, 0, exponentString.length())
  2284. && !sawExponent) {
  2285. // Process the exponent by recursively calling this method.
  2286. ParsePosition pos = new ParsePosition(position + exponentString.length());
  2287. boolean[] stat = new boolean[STATUS_LENGTH];
  2288. DigitList exponentDigits = new DigitList();
  2289.  
  2290. if (subparse(text, pos, "", Character.toString(symbols.getMinusSign()), exponentDigits, true, stat) &&
  2291. exponentDigits.fitsIntoLong(stat[STATUS_POSITIVE], true)) {
  2292. position = pos.index; // Advance past the exponent
  2293. exponent = (int)exponentDigits.getLong();
  2294. if (!stat[STATUS_POSITIVE]) {
  2295. exponent = -exponent;
  2296. }
  2297. sawExponent = true;
  2298. }
  2299. break; // Whether we fail or succeed, we exit this loop
  2300. } else {
  2301. break;
  2302. }
  2303. }
  2304.  
  2305. if (backup != -1) {
  2306. position = backup;
  2307. }
  2308.  
  2309. // If there was no decimal point we have an integer
  2310. if (!sawDecimal) {
  2311. digits.decimalAt = digitCount; // Not digits.count!
  2312. }
  2313.  
  2314. // Adjust for exponent, if any
  2315. digits.decimalAt += exponent;
  2316.  
  2317. // If none of the text string was recognized. For example, parse
  2318. // "x" with pattern "#0.00" (return index and error index both 0)
  2319. // parse "$" with pattern "$#0.00". (return index 0 and error
  2320. // index 1).
  2321. if (!sawDigit && digitCount == 0) {
  2322. parsePosition.index = oldStart;
  2323. parsePosition.errorIndex = oldStart;
  2324. return false;
  2325. }
  2326. }
  2327.  
  2328. // check for suffix
  2329. if (!isExponent) {
  2330. if (gotPositive) {
  2331. gotPositive = text.regionMatches(position,positiveSuffix,0,
  2332. positiveSuffix.length());
  2333. }
  2334. if (gotNegative) {
  2335. gotNegative = text.regionMatches(position,negativeSuffix,0,
  2336. negativeSuffix.length());
  2337. }
  2338.  
  2339. // if both match, take longest
  2340. if (gotPositive && gotNegative) {
  2341. if (positiveSuffix.length() > negativeSuffix.length()) {
  2342. gotNegative = false;
  2343. } else if (positiveSuffix.length() < negativeSuffix.length()) {
  2344. gotPositive = false;
  2345. }
  2346. }
  2347.  
  2348. // fail if neither or both
  2349. if (gotPositive == gotNegative) {
  2350. parsePosition.errorIndex = position;
  2351. return false;
  2352. }
  2353.  
  2354. parsePosition.index = position +
  2355. (gotPositive ? positiveSuffix.length() : negativeSuffix.length()); // mark success!
  2356. } else {
  2357. parsePosition.index = position;
  2358. }
  2359.  
  2360. status[STATUS_POSITIVE] = gotPositive;
  2361. if (parsePosition.index == oldStart) {
  2362. parsePosition.errorIndex = position;
  2363. return false;
  2364. }
  2365. return true;
  2366. }
  2367.  
  2368. /**
  2369. * Returns a copy of the decimal format symbols, which is generally not
  2370. * changed by the programmer or user.
  2371. * @return a copy of the desired DecimalFormatSymbols
  2372. * @see java.text.DecimalFormatSymbols
  2373. */
  2374. public DecimalFormatSymbols getDecimalFormatSymbols() {
  2375. try {
  2376. // don't allow multiple references
  2377. return (DecimalFormatSymbols) symbols.clone();
  2378. } catch (Exception foo) {
  2379. return null; // should never happen
  2380. }
  2381. }
  2382.  
  2383. /**
  2384. * Sets the decimal format symbols, which is generally not changed
  2385. * by the programmer or user.
  2386. * @param newSymbols desired DecimalFormatSymbols
  2387. * @see java.text.DecimalFormatSymbols
  2388. */
  2389. public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
  2390. try {
  2391. // don't allow multiple references
  2392. symbols = (DecimalFormatSymbols) newSymbols.clone();
  2393. expandAffixes();
  2394. fastPathCheckNeeded = true;
  2395. } catch (Exception foo) {
  2396. // should never happen
  2397. }
  2398. }
  2399.  
  2400. /**
  2401. * Get the positive prefix.
  2402. * <P>Examples: +123, $123, sFr123
  2403. *
  2404. * @return the positive prefix
  2405. */
  2406. public String getPositivePrefix () {
  2407. return positivePrefix;
  2408. }
  2409.  
  2410. /**
  2411. * Set the positive prefix.
  2412. * <P>Examples: +123, $123, sFr123
  2413. *
  2414. * @param newValue the new positive prefix
  2415. */
  2416. public void setPositivePrefix (String newValue) {
  2417. positivePrefix = newValue;
  2418. posPrefixPattern = null;
  2419. positivePrefixFieldPositions = null;
  2420. fastPathCheckNeeded = true;
  2421. }
  2422.  
  2423. /**
  2424. * Returns the FieldPositions of the fields in the prefix used for
  2425. * positive numbers. This is not used if the user has explicitly set
  2426. * a positive prefix via <code>setPositivePrefix</code>. This is
  2427. * lazily created.
  2428. *
  2429. * @return FieldPositions in positive prefix
  2430. */
  2431. private FieldPosition[] getPositivePrefixFieldPositions() {
  2432. if (positivePrefixFieldPositions == null) {
  2433. if (posPrefixPattern != null) {
  2434. positivePrefixFieldPositions = expandAffix(posPrefixPattern);
  2435. } else {
  2436. positivePrefixFieldPositions = EmptyFieldPositionArray;
  2437. }
  2438. }
  2439. return positivePrefixFieldPositions;
  2440. }
  2441.  
  2442. /**
  2443. * Get the negative prefix.
  2444. * <P>Examples: -123, ($123) (with negative suffix), sFr-123
  2445. *
  2446. * @return the negative prefix
  2447. */
  2448. public String getNegativePrefix () {
  2449. return negativePrefix;
  2450. }
  2451.  
  2452. /**
  2453. * Set the negative prefix.
  2454. * <P>Examples: -123, ($123) (with negative suffix), sFr-123
  2455. *
  2456. * @param newValue the new negative prefix
  2457. */
  2458. public void setNegativePrefix (String newValue) {
  2459. negativePrefix = newValue;
  2460. negPrefixPattern = null;
  2461. fastPathCheckNeeded = true;
  2462. }
  2463.  
  2464. /**
  2465. * Returns the FieldPositions of the fields in the prefix used for
  2466. * negative numbers. This is not used if the user has explicitly set
  2467. * a negative prefix via <code>setNegativePrefix</code>. This is
  2468. * lazily created.
  2469. *
  2470. * @return FieldPositions in positive prefix
  2471. */
  2472. private FieldPosition[] getNegativePrefixFieldPositions() {
  2473. if (negativePrefixFieldPositions == null) {
  2474. if (negPrefixPattern != null) {
  2475. negativePrefixFieldPositions = expandAffix(negPrefixPattern);
  2476. } else {
  2477. negativePrefixFieldPositions = EmptyFieldPositionArray;
  2478. }
  2479. }
  2480. return negativePrefixFieldPositions;
  2481. }
  2482.  
  2483. /**
  2484. * Get the positive suffix.
  2485. * <P>Example: 123%
  2486. *
  2487. * @return the positive suffix
  2488. */
  2489. public String getPositiveSuffix () {
  2490. return positiveSuffix;
  2491. }
  2492.  
  2493. /**
  2494. * Set the positive suffix.
  2495. * <P>Example: 123%
  2496. *
  2497. * @param newValue the new positive suffix
  2498. */
  2499. public void setPositiveSuffix (String newValue) {
  2500. positiveSuffix = newValue;
  2501. posSuffixPattern = null;
  2502. fastPathCheckNeeded = true;
  2503. }
  2504.  
  2505. /**
  2506. * Returns the FieldPositions of the fields in the suffix used for
  2507. * positive numbers. This is not used if the user has explicitly set
  2508. * a positive suffix via <code>setPositiveSuffix</code>. This is
  2509. * lazily created.
  2510. *
  2511. * @return FieldPositions in positive prefix
  2512. */
  2513. private FieldPosition[] getPositiveSuffixFieldPositions() {
  2514. if (positiveSuffixFieldPositions == null) {
  2515. if (posSuffixPattern != null) {
  2516. positiveSuffixFieldPositions = expandAffix(posSuffixPattern);
  2517. } else {
  2518. positiveSuffixFieldPositions = EmptyFieldPositionArray;
  2519. }
  2520. }
  2521. return positiveSuffixFieldPositions;
  2522. }
  2523.  
  2524. /**
  2525. * Get the negative suffix.
  2526. * <P>Examples: -123%, ($123) (with positive suffixes)
  2527. *
  2528. * @return the negative suffix
  2529. */
  2530. public String getNegativeSuffix () {
  2531. return negativeSuffix;
  2532. }
  2533.  
  2534. /**
  2535. * Set the negative suffix.
  2536. * <P>Examples: 123%
  2537. *
  2538. * @param newValue the new negative suffix
  2539. */
  2540. public void setNegativeSuffix (String newValue) {
  2541. negativeSuffix = newValue;
  2542. negSuffixPattern = null;
  2543. fastPathCheckNeeded = true;
  2544. }
  2545.  
  2546. /**
  2547. * Returns the FieldPositions of the fields in the suffix used for
  2548. * negative numbers. This is not used if the user has explicitly set
  2549. * a negative suffix via <code>setNegativeSuffix</code>. This is
  2550. * lazily created.
  2551. *
  2552. * @return FieldPositions in positive prefix
  2553. */
  2554. private FieldPosition[] getNegativeSuffixFieldPositions() {
  2555. if (negativeSuffixFieldPositions == null) {
  2556. if (negSuffixPattern != null) {
  2557. negativeSuffixFieldPositions = expandAffix(negSuffixPattern);
  2558. } else {
  2559. negativeSuffixFieldPositions = EmptyFieldPositionArray;
  2560. }
  2561. }
  2562. return negativeSuffixFieldPositions;
  2563. }
  2564.  
  2565. /**
  2566. * Gets the multiplier for use in percent, per mille, and similar
  2567. * formats.
  2568. *
  2569. * @return the multiplier
  2570. * @see #setMultiplier(int)
  2571. */
  2572. public int getMultiplier () {
  2573. return multiplier;
  2574. }
  2575.  
  2576. /**
  2577. * Sets the multiplier for use in percent, per mille, and similar
  2578. * formats.
  2579. * For a percent format, set the multiplier to 100 and the suffixes to
  2580. * have '%' (for Arabic, use the Arabic percent sign).
  2581. * For a per mille format, set the multiplier to 1000 and the suffixes to
  2582. * have '\u2030'.
  2583. *
  2584. * <P>Example: with multiplier 100, 1.23 is formatted as "123", and
  2585. * "123" is parsed into 1.23.
  2586. *
  2587. * @param newValue the new multiplier
  2588. * @see #getMultiplier
  2589. */
  2590. public void setMultiplier (int newValue) {
  2591. multiplier = newValue;
  2592. bigDecimalMultiplier = null;
  2593. bigIntegerMultiplier = null;
  2594. fastPathCheckNeeded = true;
  2595. }
  2596.  
  2597. /**
  2598. * {@inheritDoc}
  2599. */
  2600. @Override
  2601. public void setGroupingUsed(boolean newValue) {
  2602. super.setGroupingUsed(newValue);
  2603. fastPathCheckNeeded = true;
  2604. }
  2605.  
  2606. /**
  2607. * Return the grouping size. Grouping size is the number of digits between
  2608. * grouping separators in the integer portion of a number. For example,
  2609. * in the number "123,456.78", the grouping size is 3.
  2610. *
  2611. * @return the grouping size
  2612. * @see #setGroupingSize
  2613. * @see java.text.NumberFormat#isGroupingUsed
  2614. * @see java.text.DecimalFormatSymbols#getGroupingSeparator
  2615. */
  2616. public int getGroupingSize () {
  2617. return groupingSize;
  2618. }
  2619.  
  2620. /**
  2621. * Set the grouping size. Grouping size is the number of digits between
  2622. * grouping separators in the integer portion of a number. For example,
  2623. * in the number "123,456.78", the grouping size is 3.
  2624. * <br>
  2625. * The value passed in is converted to a byte, which may lose information.
  2626. *
  2627. * @param newValue the new grouping size
  2628. * @see #getGroupingSize
  2629. * @see java.text.NumberFormat#setGroupingUsed
  2630. * @see java.text.DecimalFormatSymbols#setGroupingSeparator
  2631. */
  2632. public void setGroupingSize (int newValue) {
  2633. groupingSize = (byte)newValue;
  2634. fastPathCheckNeeded = true;
  2635. }
  2636.  
  2637. /**
  2638. * Allows you to get the behavior of the decimal separator with integers.
  2639. * (The decimal separator will always appear with decimals.)
  2640. * <P>Example: Decimal ON: 12345 &rarr; 12345.; OFF: 12345 &rarr; 12345
  2641. *
  2642. * @return {@code true} if the decimal separator is always shown;
  2643. * {@code false} otherwise
  2644. */
  2645. public boolean isDecimalSeparatorAlwaysShown() {
  2646. return decimalSeparatorAlwaysShown;
  2647. }
  2648.  
  2649. /**
  2650. * Allows you to set the behavior of the decimal separator with integers.
  2651. * (The decimal separator will always appear with decimals.)
  2652. * <P>Example: Decimal ON: 12345 &rarr; 12345.; OFF: 12345 &rarr; 12345
  2653. *
  2654. * @param newValue {@code true} if the decimal separator is always shown;
  2655. * {@code false} otherwise
  2656. */
  2657. public void setDecimalSeparatorAlwaysShown(boolean newValue) {
  2658. decimalSeparatorAlwaysShown = newValue;
  2659. fastPathCheckNeeded = true;
  2660. }
  2661.  
  2662. /**
  2663. * Returns whether the {@link #parse(java.lang.String, java.text.ParsePosition)}
  2664. * method returns <code>BigDecimal</code>. The default value is false.
  2665. *
  2666. * @return {@code true} if the parse method returns BigDecimal;
  2667. * {@code false} otherwise
  2668. * @see #setParseBigDecimal
  2669. * @since 1.5
  2670. */
  2671. public boolean isParseBigDecimal() {
  2672. return parseBigDecimal;
  2673. }
  2674.  
  2675. /**
  2676. * Sets whether the {@link #parse(java.lang.String, java.text.ParsePosition)}
  2677. * method returns <code>BigDecimal</code>.
  2678. *
  2679. * @param newValue {@code true} if the parse method returns BigDecimal;
  2680. * {@code false} otherwise
  2681. * @see #isParseBigDecimal
  2682. * @since 1.5
  2683. */
  2684. public void setParseBigDecimal(boolean newValue) {
  2685. parseBigDecimal = newValue;
  2686. }
  2687.  
  2688. /**
  2689. * Standard override; no change in semantics.
  2690. */
  2691. @Override
  2692. public Object clone() {
  2693. DecimalFormat other = (DecimalFormat) super.clone();
  2694. other.symbols = (DecimalFormatSymbols) symbols.clone();
  2695. other.digitList = (DigitList) digitList.clone();
  2696.  
  2697. // Fast-path is almost stateless algorithm. The only logical state is the
  2698. // isFastPath flag. In addition fastPathCheckNeeded is a sentinel flag
  2699. // that forces recalculation of all fast-path fields when set to true.
  2700. //
  2701. // There is thus no need to clone all the fast-path fields.
  2702. // We just only need to set fastPathCheckNeeded to true when cloning,
  2703. // and init fastPathData to null as if it were a truly new instance.
  2704. // Every fast-path field will be recalculated (only once) at next usage of
  2705. // fast-path algorithm.
  2706. other.fastPathCheckNeeded = true;
  2707. other.isFastPath = false;
  2708. other.fastPathData = null;
  2709.  
  2710. return other;
  2711. }
  2712.  
  2713. /**
  2714. * Overrides equals
  2715. */
  2716. @Override
  2717. public boolean equals(Object obj)
  2718. {
  2719. if (obj == null)
  2720. return false;
  2721. if (!super.equals(obj))
  2722. return false; // super does class check
  2723. DecimalFormat other = (DecimalFormat) obj;
  2724. return ((posPrefixPattern == other.posPrefixPattern &&
  2725. positivePrefix.equals(other.positivePrefix))
  2726. || (posPrefixPattern != null &&
  2727. posPrefixPattern.equals(other.posPrefixPattern)))
  2728. && ((posSuffixPattern == other.posSuffixPattern &&
  2729. positiveSuffix.equals(other.positiveSuffix))
  2730. || (posSuffixPattern != null &&
  2731. posSuffixPattern.equals(other.posSuffixPattern)))
  2732. && ((negPrefixPattern == other.negPrefixPattern &&
  2733. negativePrefix.equals(other.negativePrefix))
  2734. || (negPrefixPattern != null &&
  2735. negPrefixPattern.equals(other.negPrefixPattern)))
  2736. && ((negSuffixPattern == other.negSuffixPattern &&
  2737. negativeSuffix.equals(other.negativeSuffix))
  2738. || (negSuffixPattern != null &&
  2739. negSuffixPattern.equals(other.negSuffixPattern)))
  2740. && multiplier == other.multiplier
  2741. && groupingSize == other.groupingSize
  2742. && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown
  2743. && parseBigDecimal == other.parseBigDecimal
  2744. && useExponentialNotation == other.useExponentialNotation
  2745. && (!useExponentialNotation ||
  2746. minExponentDigits == other.minExponentDigits)
  2747. && maximumIntegerDigits == other.maximumIntegerDigits
  2748. && minimumIntegerDigits == other.minimumIntegerDigits
  2749. && maximumFractionDigits == other.maximumFractionDigits
  2750. && minimumFractionDigits == other.minimumFractionDigits
  2751. && roundingMode == other.roundingMode
  2752. && symbols.equals(other.symbols);
  2753. }
  2754.  
  2755. /**
  2756. * Overrides hashCode
  2757. */
  2758. @Override
  2759. public int hashCode() {
  2760. return super.hashCode() * 37 + positivePrefix.hashCode();
  2761. // just enough fields for a reasonable distribution
  2762. }
  2763.  
  2764. /**
  2765. * Synthesizes a pattern string that represents the current state
  2766. * of this Format object.
  2767. *
  2768. * @return a pattern string
  2769. * @see #applyPattern
  2770. */
  2771. public String toPattern() {
  2772. return toPattern( false );
  2773. }
  2774.  
  2775. /**
  2776. * Synthesizes a localized pattern string that represents the current
  2777. * state of this Format object.
  2778. *
  2779. * @return a localized pattern string
  2780. * @see #applyPattern
  2781. */
  2782. public String toLocalizedPattern() {
  2783. return toPattern( true );
  2784. }
  2785.  
  2786. /**
  2787. * Expand the affix pattern strings into the expanded affix strings. If any
  2788. * affix pattern string is null, do not expand it. This method should be
  2789. * called any time the symbols or the affix patterns change in order to keep
  2790. * the expanded affix strings up to date.
  2791. */
  2792. private void expandAffixes() {
  2793. // Reuse one StringBuffer for better performance
  2794. StringBuffer buffer = new StringBuffer();
  2795. if (posPrefixPattern != null) {
  2796. positivePrefix = expandAffix(posPrefixPattern, buffer);
  2797. positivePrefixFieldPositions = null;
  2798. }
  2799. if (posSuffixPattern != null) {
  2800. positiveSuffix = expandAffix(posSuffixPattern, buffer);
  2801. positiveSuffixFieldPositions = null;
  2802. }
  2803. if (negPrefixPattern != null) {
  2804. negativePrefix = expandAffix(negPrefixPattern, buffer);
  2805. negativePrefixFieldPositions = null;
  2806. }
  2807. if (negSuffixPattern != null) {
  2808. negativeSuffix = expandAffix(negSuffixPattern, buffer);
  2809. negativeSuffixFieldPositions = null;
  2810. }
  2811. }
  2812.  
  2813. /**
  2814. * Expand an affix pattern into an affix string. All characters in the
  2815. * pattern are literal unless prefixed by QUOTE. The following characters
  2816. * after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
  2817. * PATTERN_MINUS, and CURRENCY_SIGN. If CURRENCY_SIGN is doubled (QUOTE +
  2818. * CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 4217
  2819. * currency code. Any other character after a QUOTE represents itself.
  2820. * QUOTE must be followed by another character; QUOTE may not occur by
  2821. * itself at the end of the pattern.
  2822. *
  2823. * @param pattern the non-null, possibly empty pattern
  2824. * @param buffer a scratch StringBuffer; its contents will be lost
  2825. * @return the expanded equivalent of pattern
  2826. */
  2827. private String expandAffix(String pattern, StringBuffer buffer) {
  2828. buffer.setLength(0);
  2829. for (int i=0; i<pattern.length(); ) {
  2830. char c = pattern.charAt(i++);
  2831. if (c == QUOTE) {
  2832. c = pattern.charAt(i++);
  2833. switch (c) {
  2834. case CURRENCY_SIGN:
  2835. if (i<pattern.length() &&
  2836. pattern.charAt(i) == CURRENCY_SIGN) {
  2837. ++i;
  2838. buffer.append(symbols.getInternationalCurrencySymbol());
  2839. } else {
  2840. buffer.append(symbols.getCurrencySymbol());
  2841. }
  2842. continue;
  2843. case PATTERN_PERCENT:
  2844. c = symbols.getPercent();
  2845. break;
  2846. case PATTERN_PER_MILLE:
  2847. c = symbols.getPerMill();
  2848. break;
  2849. case PATTERN_MINUS:
  2850. c = symbols.getMinusSign();
  2851. break;
  2852. }
  2853. }
  2854. buffer.append(c);
  2855. }
  2856. return buffer.toString();
  2857. }
  2858.  
  2859. /**
  2860. * Expand an affix pattern into an array of FieldPositions describing
  2861. * how the pattern would be expanded.
  2862. * All characters in the
  2863. * pattern are literal unless prefixed by QUOTE. The following characters
  2864. * after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
  2865. * PATTERN_MINUS, and CURRENCY_SIGN. If CURRENCY_SIGN is doubled (QUOTE +
  2866. * CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 4217
  2867. * currency code. Any other character after a QUOTE represents itself.
  2868. * QUOTE must be followed by another character; QUOTE may not occur by
  2869. * itself at the end of the pattern.
  2870. *
  2871. * @param pattern the non-null, possibly empty pattern
  2872. * @return FieldPosition array of the resulting fields.
  2873. */
  2874. private FieldPosition[] expandAffix(String pattern) {
  2875. ArrayList<FieldPosition> positions = null;
  2876. int stringIndex = 0;
  2877. for (int i=0; i<pattern.length(); ) {
  2878. char c = pattern.charAt(i++);
  2879. if (c == QUOTE) {
  2880. int field = -1;
  2881. Format.Field fieldID = null;
  2882. c = pattern.charAt(i++);
  2883. switch (c) {
  2884. case CURRENCY_SIGN:
  2885. String string;
  2886. if (i<pattern.length() &&
  2887. pattern.charAt(i) == CURRENCY_SIGN) {
  2888. ++i;
  2889. string = symbols.getInternationalCurrencySymbol();
  2890. } else {
  2891. string = symbols.getCurrencySymbol();
  2892. }
  2893. if (string.length() > 0) {
  2894. if (positions == null) {
  2895. positions = new ArrayList<>(2);
  2896. }
  2897. FieldPosition fp = new FieldPosition(Field.CURRENCY);
  2898. fp.setBeginIndex(stringIndex);
  2899. fp.setEndIndex(stringIndex + string.length());
  2900. positions.add(fp);
  2901. stringIndex += string.length();
  2902. }
  2903. continue;
  2904. case PATTERN_PERCENT:
  2905. c = symbols.getPercent();
  2906. field = -1;
  2907. fieldID = Field.PERCENT;
  2908. break;
  2909. case PATTERN_PER_MILLE:
  2910. c = symbols.getPerMill();
  2911. field = -1;
  2912. fieldID = Field.PERMILLE;
  2913. break;
  2914. case PATTERN_MINUS:
  2915. c = symbols.getMinusSign();
  2916. field = -1;
  2917. fieldID = Field.SIGN;
  2918. break;
  2919. }
  2920. if (fieldID != null) {
  2921. if (positions == null) {
  2922. positions = new ArrayList<>(2);
  2923. }
  2924. FieldPosition fp = new FieldPosition(fieldID, field);
  2925. fp.setBeginIndex(stringIndex);
  2926. fp.setEndIndex(stringIndex + 1);
  2927. positions.add(fp);
  2928. }
  2929. }
  2930. stringIndex++;
  2931. }
  2932. if (positions != null) {
  2933. return positions.toArray(EmptyFieldPositionArray);
  2934. }
  2935. return EmptyFieldPositionArray;
  2936. }
  2937.  
  2938. /**
  2939. * Appends an affix pattern to the given StringBuffer, quoting special
  2940. * characters as needed. Uses the internal affix pattern, if that exists,
  2941. * or the literal affix, if the internal affix pattern is null. The
  2942. * appended string will generate the same affix pattern (or literal affix)
  2943. * when passed to toPattern().
  2944. *
  2945. * @param buffer the affix string is appended to this
  2946. * @param affixPattern a pattern such as posPrefixPattern; may be null
  2947. * @param expAffix a corresponding expanded affix, such as positivePrefix.
  2948. * Ignored unless affixPattern is null. If affixPattern is null, then
  2949. * expAffix is appended as a literal affix.
  2950. * @param localized true if the appended pattern should contain localized
  2951. * pattern characters; otherwise, non-localized pattern chars are appended
  2952. */
  2953. private void appendAffix(StringBuffer buffer, String affixPattern,
  2954. String expAffix, boolean localized) {
  2955. if (affixPattern == null) {
  2956. appendAffix(buffer, expAffix, localized);
  2957. } else {
  2958. int i;
  2959. for (int pos=0; pos<affixPattern.length(); pos=i) {
  2960. i = affixPattern.indexOf(QUOTE, pos);
  2961. if (i < 0) {
  2962. appendAffix(buffer, affixPattern.substring(pos), localized);
  2963. break;
  2964. }
  2965. if (i > pos) {
  2966. appendAffix(buffer, affixPattern.substring(pos, i), localized);
  2967. }
  2968. char c = affixPattern.charAt(++i);
  2969. ++i;
  2970. if (c == QUOTE) {
  2971. buffer.append(c);
  2972. // Fall through and append another QUOTE below
  2973. } else if (c == CURRENCY_SIGN &&
  2974. i<affixPattern.length() &&
  2975. affixPattern.charAt(i) == CURRENCY_SIGN) {
  2976. ++i;
  2977. buffer.append(c);
  2978. // Fall through and append another CURRENCY_SIGN below
  2979. } else if (localized) {
  2980. switch (c) {
  2981. case PATTERN_PERCENT:
  2982. c = symbols.getPercent();
  2983. break;
  2984. case PATTERN_PER_MILLE:
  2985. c = symbols.getPerMill();
  2986. break;
  2987. case PATTERN_MINUS:
  2988. c = symbols.getMinusSign();
  2989. break;
  2990. }
  2991. }
  2992. buffer.append(c);
  2993. }
  2994. }
  2995. }
  2996.  
  2997. /**
  2998. * Append an affix to the given StringBuffer, using quotes if
  2999. * there are special characters. Single quotes themselves must be
  3000. * escaped in either case.
  3001. */
  3002. private void appendAffix(StringBuffer buffer, String affix, boolean localized) {
  3003. boolean needQuote;
  3004. if (localized) {
  3005. needQuote = affix.indexOf(symbols.getZeroDigit()) >= 0
  3006. || affix.indexOf(symbols.getGroupingSeparator()) >= 0
  3007. || affix.indexOf(symbols.getDecimalSeparator()) >= 0
  3008. || affix.indexOf(symbols.getPercent()) >= 0
  3009. || affix.indexOf(symbols.getPerMill()) >= 0
  3010. || affix.indexOf(symbols.getDigit()) >= 0
  3011. || affix.indexOf(symbols.getPatternSeparator()) >= 0
  3012. || affix.indexOf(symbols.getMinusSign()) >= 0
  3013. || affix.indexOf(CURRENCY_SIGN) >= 0;
  3014. } else {
  3015. needQuote = affix.indexOf(PATTERN_ZERO_DIGIT) >= 0
  3016. || affix.indexOf(PATTERN_GROUPING_SEPARATOR) >= 0
  3017. || affix.indexOf(PATTERN_DECIMAL_SEPARATOR) >= 0
  3018. || affix.indexOf(PATTERN_PERCENT) >= 0
  3019. || affix.indexOf(PATTERN_PER_MILLE) >= 0
  3020. || affix.indexOf(PATTERN_DIGIT) >= 0
  3021. || affix.indexOf(PATTERN_SEPARATOR) >= 0
  3022. || affix.indexOf(PATTERN_MINUS) >= 0
  3023. || affix.indexOf(CURRENCY_SIGN) >= 0;
  3024. }
  3025. if (needQuote) buffer.append('\'');
  3026. if (affix.indexOf('\'') < 0) buffer.append(affix);
  3027. else {
  3028. for (int j=0; j<affix.length(); ++j) {
  3029. char c = affix.charAt(j);
  3030. buffer.append(c);
  3031. if (c == '\'') buffer.append(c);
  3032. }
  3033. }
  3034. if (needQuote) buffer.append('\'');
  3035. }
  3036.  
  3037. /**
  3038. * Does the real work of generating a pattern. */
  3039. private String toPattern(boolean localized) {
  3040. StringBuffer result = new StringBuffer();
  3041. for (int j = 1; j >= 0; --j) {
  3042. if (j == 1)
  3043. appendAffix(result, posPrefixPattern, positivePrefix, localized);
  3044. else appendAffix(result, negPrefixPattern, negativePrefix, localized);
  3045. int i;
  3046. int digitCount = useExponentialNotation
  3047. ? getMaximumIntegerDigits()
  3048. : Math.max(groupingSize, getMinimumIntegerDigits())+1;
  3049. for (i = digitCount; i > 0; --i) {
  3050. if (i != digitCount && isGroupingUsed() && groupingSize != 0 &&
  3051. i % groupingSize == 0) {
  3052. result.append(localized ? symbols.getGroupingSeparator() :
  3053. PATTERN_GROUPING_SEPARATOR);
  3054. }
  3055. result.append(i <= getMinimumIntegerDigits()
  3056. ? (localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT)
  3057. : (localized ? symbols.getDigit() : PATTERN_DIGIT));
  3058. }
  3059. if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown)
  3060. result.append(localized ? symbols.getDecimalSeparator() :
  3061. PATTERN_DECIMAL_SEPARATOR);
  3062. for (i = 0; i < getMaximumFractionDigits(); ++i) {
  3063. if (i < getMinimumFractionDigits()) {
  3064. result.append(localized ? symbols.getZeroDigit() :
  3065. PATTERN_ZERO_DIGIT);
  3066. } else {
  3067. result.append(localized ? symbols.getDigit() :
  3068. PATTERN_DIGIT);
  3069. }
  3070. }
  3071. if (useExponentialNotation)
  3072. {
  3073. result.append(localized ? symbols.getExponentSeparator() :
  3074. PATTERN_EXPONENT);
  3075. for (i=0; i<minExponentDigits; ++i)
  3076. result.append(localized ? symbols.getZeroDigit() :
  3077. PATTERN_ZERO_DIGIT);
  3078. }
  3079. if (j == 1) {
  3080. appendAffix(result, posSuffixPattern, positiveSuffix, localized);
  3081. if ((negSuffixPattern == posSuffixPattern && // n == p == null
  3082. negativeSuffix.equals(positiveSuffix))
  3083. || (negSuffixPattern != null &&
  3084. negSuffixPattern.equals(posSuffixPattern))) {
  3085. if ((negPrefixPattern != null && posPrefixPattern != null &&
  3086. negPrefixPattern.equals("'-" + posPrefixPattern)) ||
  3087. (negPrefixPattern == posPrefixPattern && // n == p == null
  3088. negativePrefix.equals(symbols.getMinusSign() + positivePrefix)))
  3089. break;
  3090. }
  3091. result.append(localized ? symbols.getPatternSeparator() :
  3092. PATTERN_SEPARATOR);
  3093. } else appendAffix(result, negSuffixPattern, negativeSuffix, localized);
  3094. }
  3095. return result.toString();
  3096. }
  3097.  
  3098. /**
  3099. * Apply the given pattern to this Format object. A pattern is a
  3100. * short-hand specification for the various formatting properties.
  3101. * These properties can also be changed individually through the
  3102. * various setter methods.
  3103. * <p>
  3104. * There is no limit to integer digits set
  3105. * by this routine, since that is the typical end-user desire;
  3106. * use setMaximumInteger if you want to set a real value.
  3107. * For negative numbers, use a second pattern, separated by a semicolon
  3108. * <P>Example <code>"#,#00.0#"</code> &rarr; 1,234.56
  3109. * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
  3110. * a maximum of 2 fraction digits.
  3111. * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in
  3112. * parentheses.
  3113. * <p>In negative patterns, the minimum and maximum counts are ignored;
  3114. * these are presumed to be set in the positive pattern.
  3115. *
  3116. * @param pattern a new pattern
  3117. * @exception NullPointerException if <code>pattern</code> is null
  3118. * @exception IllegalArgumentException if the given pattern is invalid.
  3119. */
  3120. public void applyPattern(String pattern) {
  3121. applyPattern(pattern, false);
  3122. }
  3123.  
  3124. /**
  3125. * Apply the given pattern to this Format object. The pattern
  3126. * is assumed to be in a localized notation. A pattern is a
  3127. * short-hand specification for the various formatting properties.
  3128. * These properties can also be changed individually through the
  3129. * various setter methods.
  3130. * <p>
  3131. * There is no limit to integer digits set
  3132. * by this routine, since that is the typical end-user desire;
  3133. * use setMaximumInteger if you want to set a real value.
  3134. * For negative numbers, use a second pattern, separated by a semicolon
  3135. * <P>Example <code>"#,#00.0#"</code> &rarr; 1,234.56
  3136. * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
  3137. * a maximum of 2 fraction digits.
  3138. * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in
  3139. * parentheses.
  3140. * <p>In negative patterns, the minimum and maximum counts are ignored;
  3141. * these are presumed to be set in the positive pattern.
  3142. *
  3143. * @param pattern a new pattern
  3144. * @exception NullPointerException if <code>pattern</code> is null
  3145. * @exception IllegalArgumentException if the given pattern is invalid.
  3146. */
  3147. public void applyLocalizedPattern(String pattern) {
  3148. applyPattern(pattern, true);
  3149. }
  3150.  
  3151. /**
  3152. * Does the real work of applying a pattern.
  3153. */
  3154. private void applyPattern(String pattern, boolean localized) {
  3155. char zeroDigit = PATTERN_ZERO_DIGIT;
  3156. char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
  3157. char decimalSeparator = PATTERN_DECIMAL_SEPARATOR;
  3158. char percent = PATTERN_PERCENT;
  3159. char perMill = PATTERN_PER_MILLE;
  3160. char digit = PATTERN_DIGIT;
  3161. char separator = PATTERN_SEPARATOR;
  3162. String exponent = PATTERN_EXPONENT;
  3163. char minus = PATTERN_MINUS;
  3164. if (localized) {
  3165. zeroDigit = symbols.getZeroDigit();
  3166. groupingSeparator = symbols.getGroupingSeparator();
  3167. decimalSeparator = symbols.getDecimalSeparator();
  3168. percent = symbols.getPercent();
  3169. perMill = symbols.getPerMill();
  3170. digit = symbols.getDigit();
  3171. separator = symbols.getPatternSeparator();
  3172. exponent = symbols.getExponentSeparator();
  3173. minus = symbols.getMinusSign();
  3174. }
  3175. boolean gotNegative = false;
  3176. decimalSeparatorAlwaysShown = false;
  3177. isCurrencyFormat = false;
  3178. useExponentialNotation = false;
  3179.  
  3180. // Two variables are used to record the subrange of the pattern
  3181. // occupied by phase 1. This is used during the processing of the
  3182. // second pattern (the one representing negative numbers) to ensure
  3183. // that no deviation exists in phase 1 between the two patterns.
  3184. int phaseOneStart = 0;
  3185. int phaseOneLength = 0;
  3186.  
  3187. int start = 0;
  3188. for (int j = 1; j >= 0 && start < pattern.length(); --j) {
  3189. boolean inQuote = false;
  3190. StringBuffer prefix = new StringBuffer();
  3191. StringBuffer suffix = new StringBuffer();
  3192. int decimalPos = -1;
  3193. int multiplier = 1;
  3194. int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0;
  3195. byte groupingCount = -1;
  3196.  
  3197. // The phase ranges from 0 to 2. Phase 0 is the prefix. Phase 1 is
  3198. // the section of the pattern with digits, decimal separator,
  3199. // grouping characters. Phase 2 is the suffix. In phases 0 and 2,
  3200. // percent, per mille, and currency symbols are recognized and
  3201. // translated. The separation of the characters into phases is
  3202. // strictly enforced; if phase 1 characters are to appear in the
  3203. // suffix, for example, they must be quoted.
  3204. int phase = 0;
  3205.  
  3206. // The affix is either the prefix or the suffix.
  3207. StringBuffer affix = prefix;
  3208.  
  3209. for (int pos = start; pos < pattern.length(); ++pos) {
  3210. char ch = pattern.charAt(pos);
  3211. switch (phase) {
  3212. case 0:
  3213. case 2:
  3214. // Process the prefix / suffix characters
  3215. if (inQuote) {
  3216. // A quote within quotes indicates either the closing
  3217. // quote or two quotes, which is a quote literal. That
  3218. // is, we have the second quote in 'do' or 'don''t'.
  3219. if (ch == QUOTE) {
  3220. if ((pos+1) < pattern.length() &&
  3221. pattern.charAt(pos+1) == QUOTE) {
  3222. ++pos;
  3223. affix.append("''"); // 'don''t'
  3224. } else {
  3225. inQuote = false; // 'do'
  3226. }
  3227. continue;
  3228. }
  3229. } else {
  3230. // Process unquoted characters seen in prefix or suffix
  3231. // phase.
  3232. if (ch == digit ||
  3233. ch == zeroDigit ||
  3234. ch == groupingSeparator ||
  3235. ch == decimalSeparator) {
  3236. phase = 1;
  3237. if (j == 1) {
  3238. phaseOneStart = pos;
  3239. }
  3240. --pos; // Reprocess this character
  3241. continue;
  3242. } else if (ch == CURRENCY_SIGN) {
  3243. // Use lookahead to determine if the currency sign
  3244. // is doubled or not.
  3245. boolean doubled = (pos + 1) < pattern.length() &&
  3246. pattern.charAt(pos + 1) == CURRENCY_SIGN;
  3247. if (doubled) { // Skip over the doubled character
  3248. ++pos;
  3249. }
  3250. isCurrencyFormat = true;
  3251. affix.append(doubled ? "'\u00A4\u00A4" : "'\u00A4");
  3252. continue;
  3253. } else if (ch == QUOTE) {
  3254. // A quote outside quotes indicates either the
  3255. // opening quote or two quotes, which is a quote
  3256. // literal. That is, we have the first quote in 'do'
  3257. // or o''clock.
  3258. if (ch == QUOTE) {
  3259. if ((pos+1) < pattern.length() &&
  3260. pattern.charAt(pos+1) == QUOTE) {
  3261. ++pos;
  3262. affix.append("''"); // o''clock
  3263. } else {
  3264. inQuote = true; // 'do'
  3265. }
  3266. continue;
  3267. }
  3268. } else if (ch == separator) {
  3269. // Don't allow separators before we see digit
  3270. // characters of phase 1, and don't allow separators
  3271. // in the second pattern (j == 0).
  3272. if (phase == 0 || j == 0) {
  3273. throw new IllegalArgumentException("Unquoted special character '" +
  3274. ch + "' in pattern \"" + pattern + '"');
  3275. }
  3276. start = pos + 1;
  3277. pos = pattern.length();
  3278. continue;
  3279. }
  3280.  
  3281. // Next handle characters which are appended directly.
  3282. else if (ch == percent) {
  3283. if (multiplier != 1) {
  3284. throw new IllegalArgumentException("Too many percent/per mille characters in pattern \"" +
  3285. pattern + '"');
  3286. }
  3287. multiplier = 100;
  3288. affix.append("'%");
  3289. continue;
  3290. } else if (ch == perMill) {
  3291. if (multiplier != 1) {
  3292. throw new IllegalArgumentException("Too many percent/per mille characters in pattern \"" +
  3293. pattern + '"');
  3294. }
  3295. multiplier = 1000;
  3296. affix.append("'\u2030");
  3297. continue;
  3298. } else if (ch == minus) {
  3299. affix.append("'-");
  3300. continue;
  3301. }
  3302. }
  3303. // Note that if we are within quotes, or if this is an
  3304. // unquoted, non-special character, then we usually fall
  3305. // through to here.
  3306. affix.append(ch);
  3307. break;
  3308.  
  3309. case 1:
  3310. // Phase one must be identical in the two sub-patterns. We
  3311. // enforce this by doing a direct comparison. While
  3312. // processing the first sub-pattern, we just record its
  3313. // length. While processing the second, we compare
  3314. // characters.
  3315. if (j == 1) {
  3316. ++phaseOneLength;
  3317. } else {
  3318. if (--phaseOneLength == 0) {
  3319. phase = 2;
  3320. affix = suffix;
  3321. }
  3322. continue;
  3323. }
  3324.  
  3325. // Process the digits, decimal, and grouping characters. We
  3326. // record five pieces of information. We expect the digits
  3327. // to occur in the pattern ####0000.####, and we record the
  3328. // number of left digits, zero (central) digits, and right
  3329. // digits. The position of the last grouping character is
  3330. // recorded (should be somewhere within the first two blocks
  3331. // of characters), as is the position of the decimal point,
  3332. // if any (should be in the zero digits). If there is no
  3333. // decimal point, then there should be no right digits.
  3334. if (ch == digit) {
  3335. if (zeroDigitCount > 0) {
  3336. ++digitRightCount;
  3337. } else {
  3338. ++digitLeftCount;
  3339. }
  3340. if (groupingCount >= 0 && decimalPos < 0) {
  3341. ++groupingCount;
  3342. }
  3343. } else if (ch == zeroDigit) {
  3344. if (digitRightCount > 0) {
  3345. throw new IllegalArgumentException("Unexpected '0' in pattern \"" +
  3346. pattern + '"');
  3347. }
  3348. ++zeroDigitCount;
  3349. if (groupingCount >= 0 && decimalPos < 0) {
  3350. ++groupingCount;
  3351. }
  3352. } else if (ch == groupingSeparator) {
  3353. groupingCount = 0;
  3354. } else if (ch == decimalSeparator) {
  3355. if (decimalPos >= 0) {
  3356. throw new IllegalArgumentException("Multiple decimal separators in pattern \"" +
  3357. pattern + '"');
  3358. }
  3359. decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
  3360. } else if (pattern.regionMatches(pos, exponent, 0, exponent.length())){
  3361. if (useExponentialNotation) {
  3362. throw new IllegalArgumentException("Multiple exponential " +
  3363. "symbols in pattern \"" + pattern + '"');
  3364. }
  3365. useExponentialNotation = true;
  3366. minExponentDigits = 0;
  3367.  
  3368. // Use lookahead to parse out the exponential part
  3369. // of the pattern, then jump into phase 2.
  3370. pos = pos+exponent.length();
  3371. while (pos < pattern.length() &&
  3372. pattern.charAt(pos) == zeroDigit) {
  3373. ++minExponentDigits;
  3374. ++phaseOneLength;
  3375. ++pos;
  3376. }
  3377.  
  3378. if ((digitLeftCount + zeroDigitCount) < 1 ||
  3379. minExponentDigits < 1) {
  3380. throw new IllegalArgumentException("Malformed exponential " +
  3381. "pattern \"" + pattern + '"');
  3382. }
  3383.  
  3384. // Transition to phase 2
  3385. phase = 2;
  3386. affix = suffix;
  3387. --pos;
  3388. continue;
  3389. } else {
  3390. phase = 2;
  3391. affix = suffix;
  3392. --pos;
  3393. --phaseOneLength;
  3394. continue;
  3395. }
  3396. break;
  3397. }
  3398. }
  3399.  
  3400. // Handle patterns with no '0' pattern character. These patterns
  3401. // are legal, but must be interpreted. "##.###" -> "#0.###".
  3402. // ".###" -> ".0##".
  3403. /* We allow patterns of the form "####" to produce a zeroDigitCount
  3404. * of zero (got that?); although this seems like it might make it
  3405. * possible for format() to produce empty strings, format() checks
  3406. * for this condition and outputs a zero digit in this situation.
  3407. * Having a zeroDigitCount of zero yields a minimum integer digits
  3408. * of zero, which allows proper round-trip patterns. That is, we
  3409. * don't want "#" to become "#0" when toPattern() is called (even
  3410. * though that's what it really is, semantically).
  3411. */
  3412. if (zeroDigitCount == 0 && digitLeftCount > 0 && decimalPos >= 0) {
  3413. // Handle "###.###" and "###." and ".###"
  3414. int n = decimalPos;
  3415. if (n == 0) { // Handle ".###"
  3416. ++n;
  3417. }
  3418. digitRightCount = digitLeftCount - n;
  3419. digitLeftCount = n - 1;
  3420. zeroDigitCount = 1;
  3421. }
  3422.  
  3423. // Do syntax checking on the digits.
  3424. if ((decimalPos < 0 && digitRightCount > 0) ||
  3425. (decimalPos >= 0 && (decimalPos < digitLeftCount ||
  3426. decimalPos > (digitLeftCount + zeroDigitCount))) ||
  3427. groupingCount == 0 || inQuote) {
  3428. throw new IllegalArgumentException("Malformed pattern \"" +
  3429. pattern + '"');
  3430. }
  3431.  
  3432. if (j == 1) {
  3433. posPrefixPattern = prefix.toString();
  3434. posSuffixPattern = suffix.toString();
  3435. negPrefixPattern = posPrefixPattern; // assume these for now
  3436. negSuffixPattern = posSuffixPattern;
  3437. int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
  3438. /* The effectiveDecimalPos is the position the decimal is at or
  3439. * would be at if there is no decimal. Note that if decimalPos<0,
  3440. * then digitTotalCount == digitLeftCount + zeroDigitCount.
  3441. */
  3442. int effectiveDecimalPos = decimalPos >= 0 ?
  3443. decimalPos : digitTotalCount;
  3444. setMinimumIntegerDigits(effectiveDecimalPos - digitLeftCount);
  3445. setMaximumIntegerDigits(useExponentialNotation ?
  3446. digitLeftCount + getMinimumIntegerDigits() :
  3447. MAXIMUM_INTEGER_DIGITS);
  3448. setMaximumFractionDigits(decimalPos >= 0 ?
  3449. (digitTotalCount - decimalPos) : 0);
  3450. setMinimumFractionDigits(decimalPos >= 0 ?
  3451. (digitLeftCount + zeroDigitCount - decimalPos) : 0);
  3452. setGroupingUsed(groupingCount > 0);
  3453. this.groupingSize = (groupingCount > 0) ? groupingCount : 0;
  3454. this.multiplier = multiplier;
  3455. setDecimalSeparatorAlwaysShown(decimalPos == 0 ||
  3456. decimalPos == digitTotalCount);
  3457. } else {
  3458. negPrefixPattern = prefix.toString();
  3459. negSuffixPattern = suffix.toString();
  3460. gotNegative = true;
  3461. }
  3462. }
  3463.  
  3464. if (pattern.length() == 0) {
  3465. posPrefixPattern = posSuffixPattern = "";
  3466. setMinimumIntegerDigits(0);
  3467. setMaximumIntegerDigits(MAXIMUM_INTEGER_DIGITS);
  3468. setMinimumFractionDigits(0);
  3469. setMaximumFractionDigits(MAXIMUM_FRACTION_DIGITS);
  3470. }
  3471.  
  3472. // If there was no negative pattern, or if the negative pattern is
  3473. // identical to the positive pattern, then prepend the minus sign to
  3474. // the positive pattern to form the negative pattern.
  3475. if (!gotNegative ||
  3476. (negPrefixPattern.equals(posPrefixPattern)
  3477. && negSuffixPattern.equals(posSuffixPattern))) {
  3478. negSuffixPattern = posSuffixPattern;
  3479. negPrefixPattern = "'-" + posPrefixPattern;
  3480. }
  3481.  
  3482. expandAffixes();
  3483. }
  3484.  
  3485. /**
  3486. * Sets the maximum number of digits allowed in the integer portion of a
  3487. * number.
  3488. * For formatting numbers other than <code>BigInteger</code> and
  3489. * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
  3490. * 309 is used. Negative input values are replaced with 0.
  3491. * @see NumberFormat#setMaximumIntegerDigits
  3492. */
  3493. @Override
  3494. public void setMaximumIntegerDigits(int newValue) {
  3495. maximumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS);
  3496. super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
  3497. DOUBLE_INTEGER_DIGITS : maximumIntegerDigits);
  3498. if (minimumIntegerDigits > maximumIntegerDigits) {
  3499. minimumIntegerDigits = maximumIntegerDigits;
  3500. super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
  3501. DOUBLE_INTEGER_DIGITS : minimumIntegerDigits);
  3502. }
  3503. fastPathCheckNeeded = true;
  3504. }
  3505.  
  3506. /**
  3507. * Sets the minimum number of digits allowed in the integer portion of a
  3508. * number.
  3509. * For formatting numbers other than <code>BigInteger</code> and
  3510. * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
  3511. * 309 is used. Negative input values are replaced with 0.
  3512. * @see NumberFormat#setMinimumIntegerDigits
  3513. */
  3514. @Override
  3515. public void setMinimumIntegerDigits(int newValue) {
  3516. minimumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS);
  3517. super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
  3518. DOUBLE_INTEGER_DIGITS : minimumIntegerDigits);
  3519. if (minimumIntegerDigits > maximumIntegerDigits) {
  3520. maximumIntegerDigits = minimumIntegerDigits;
  3521. super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
  3522. DOUBLE_INTEGER_DIGITS : maximumIntegerDigits);
  3523. }
  3524. fastPathCheckNeeded = true;
  3525. }
  3526.  
  3527. /**
  3528. * Sets the maximum number of digits allowed in the fraction portion of a
  3529. * number.
  3530. * For formatting numbers other than <code>BigInteger</code> and
  3531. * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
  3532. * 340 is used. Negative input values are replaced with 0.
  3533. * @see NumberFormat#setMaximumFractionDigits
  3534. */
  3535. @Override
  3536. public void setMaximumFractionDigits(int newValue) {
  3537. maximumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS);
  3538. super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
  3539. DOUBLE_FRACTION_DIGITS : maximumFractionDigits);
  3540. if (minimumFractionDigits > maximumFractionDigits) {
  3541. minimumFractionDigits = maximumFractionDigits;
  3542. super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
  3543. DOUBLE_FRACTION_DIGITS : minimumFractionDigits);
  3544. }
  3545. fastPathCheckNeeded = true;
  3546. }
  3547.  
  3548. /**
  3549. * Sets the minimum number of digits allowed in the fraction portion of a
  3550. * number.
  3551. * For formatting numbers other than <code>BigInteger</code> and
  3552. * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
  3553. * 340 is used. Negative input values are replaced with 0.
  3554. * @see NumberFormat#setMinimumFractionDigits
  3555. */
  3556. @Override
  3557. public void setMinimumFractionDigits(int newValue) {
  3558. minimumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS);
  3559. super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
  3560. DOUBLE_FRACTION_DIGITS : minimumFractionDigits);
  3561. if (minimumFractionDigits > maximumFractionDigits) {
  3562. maximumFractionDigits = minimumFractionDigits;
  3563. super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
  3564. DOUBLE_FRACTION_DIGITS : maximumFractionDigits);
  3565. }
  3566. fastPathCheckNeeded = true;
  3567. }
  3568.  
  3569. /**
  3570. * Gets the maximum number of digits allowed in the integer portion of a
  3571. * number.
  3572. * For formatting numbers other than <code>BigInteger</code> and
  3573. * <code>BigDecimal</code> objects, the lower of the return value and
  3574. * 309 is used.
  3575. * @see #setMaximumIntegerDigits
  3576. */
  3577. @Override
  3578. public int getMaximumIntegerDigits() {
  3579. return maximumIntegerDigits;
  3580. }
  3581.  
  3582. /**
  3583. * Gets the minimum number of digits allowed in the integer portion of a
  3584. * number.
  3585. * For formatting numbers other than <code>BigInteger</code> and
  3586. * <code>BigDecimal</code> objects, the lower of the return value and
  3587. * 309 is used.
  3588. * @see #setMinimumIntegerDigits
  3589. */
  3590. @Override
  3591. public int getMinimumIntegerDigits() {
  3592. return minimumIntegerDigits;
  3593. }
  3594.  
  3595. /**
  3596. * Gets the maximum number of digits allowed in the fraction portion of a
  3597. * number.
  3598. * For formatting numbers other than <code>BigInteger</code> and
  3599. * <code>BigDecimal</code> objects, the lower of the return value and
  3600. * 340 is used.
  3601. * @see #setMaximumFractionDigits
  3602. */
  3603. @Override
  3604. public int getMaximumFractionDigits() {
  3605. return maximumFractionDigits;
  3606. }
  3607.  
  3608. /**
  3609. * Gets the minimum number of digits allowed in the fraction portion of a
  3610. * number.
  3611. * For formatting numbers other than <code>BigInteger</code> and
  3612. * <code>BigDecimal</code> objects, the lower of the return value and
  3613. * 340 is used.
  3614. * @see #setMinimumFractionDigits
  3615. */
  3616. @Override
  3617. public int getMinimumFractionDigits() {
  3618. return minimumFractionDigits;
  3619. }
  3620.  
  3621. /**
  3622. * Gets the currency used by this decimal format when formatting
  3623. * currency values.
  3624. * The currency is obtained by calling
  3625. * {@link DecimalFormatSymbols#getCurrency DecimalFormatSymbols.getCurrency}
  3626. * on this number format's symbols.
  3627. *
  3628. * @return the currency used by this decimal format, or <code>null</code>
  3629. * @since 1.4
  3630. */
  3631. @Override
  3632. public Currency getCurrency() {
  3633. return symbols.getCurrency();
  3634. }
  3635.  
  3636. /**
  3637. * Sets the currency used by this number format when formatting
  3638. * currency values. This does not update the minimum or maximum
  3639. * number of fraction digits used by the number format.
  3640. * The currency is set by calling
  3641. * {@link DecimalFormatSymbols#setCurrency DecimalFormatSymbols.setCurrency}
  3642. * on this number format's symbols.
  3643. *
  3644. * @param currency the new currency to be used by this decimal format
  3645. * @exception NullPointerException if <code>currency</code> is null
  3646. * @since 1.4
  3647. */
  3648. @Override
  3649. public void setCurrency(Currency currency) {
  3650. if (currency != symbols.getCurrency()) {
  3651. symbols.setCurrency(currency);
  3652. if (isCurrencyFormat) {
  3653. expandAffixes();
  3654. }
  3655. }
  3656. fastPathCheckNeeded = true;
  3657. }
  3658.  
  3659. /**
  3660. * Gets the {@link java.math.RoundingMode} used in this DecimalFormat.
  3661. *
  3662. * @return The <code>RoundingMode</code> used for this DecimalFormat.
  3663. * @see #setRoundingMode(RoundingMode)
  3664. * @since 1.6
  3665. */
  3666. @Override
  3667. public RoundingMode getRoundingMode() {
  3668. return roundingMode;
  3669. }
  3670.  
  3671. /**
  3672. * Sets the {@link java.math.RoundingMode} used in this DecimalFormat.
  3673. *
  3674. * @param roundingMode The <code>RoundingMode</code> to be used
  3675. * @see #getRoundingMode()
  3676. * @exception NullPointerException if <code>roundingMode</code> is null.
  3677. * @since 1.6
  3678. */
  3679. @Override
  3680. public void setRoundingMode(RoundingMode roundingMode) {
  3681. if (roundingMode == null) {
  3682. throw new NullPointerException();
  3683. }
  3684.  
  3685. this.roundingMode = roundingMode;
  3686. digitList.setRoundingMode(roundingMode);
  3687. fastPathCheckNeeded = true;
  3688. }
  3689.  
  3690. /**
  3691. * Reads the default serializable fields from the stream and performs
  3692. * validations and adjustments for older serialized versions. The
  3693. * validations and adjustments are:
  3694. * <ol>
  3695. * <li>
  3696. * Verify that the superclass's digit count fields correctly reflect
  3697. * the limits imposed on formatting numbers other than
  3698. * <code>BigInteger</code> and <code>BigDecimal</code> objects. These
  3699. * limits are stored in the superclass for serialization compatibility
  3700. * with older versions, while the limits for <code>BigInteger</code> and
  3701. * <code>BigDecimal</code> objects are kept in this class.
  3702. * If, in the superclass, the minimum or maximum integer digit count is
  3703. * larger than <code>DOUBLE_INTEGER_DIGITS</code> or if the minimum or
  3704. * maximum fraction digit count is larger than
  3705. * <code>DOUBLE_FRACTION_DIGITS</code>, then the stream data is invalid
  3706. * and this method throws an <code>InvalidObjectException</code>.
  3707. * <li>
  3708. * If <code>serialVersionOnStream</code> is less than 4, initialize
  3709. * <code>roundingMode</code> to {@link java.math.RoundingMode#HALF_EVEN
  3710. * RoundingMode.HALF_EVEN}. This field is new with version 4.
  3711. * <li>
  3712. * If <code>serialVersionOnStream</code> is less than 3, then call
  3713. * the setters for the minimum and maximum integer and fraction digits with
  3714. * the values of the corresponding superclass getters to initialize the
  3715. * fields in this class. The fields in this class are new with version 3.
  3716. * <li>
  3717. * If <code>serialVersionOnStream</code> is less than 1, indicating that
  3718. * the stream was written by JDK 1.1, initialize
  3719. * <code>useExponentialNotation</code>
  3720. * to false, since it was not present in JDK 1.1.
  3721. * <li>
  3722. * Set <code>serialVersionOnStream</code> to the maximum allowed value so
  3723. * that default serialization will work properly if this object is streamed
  3724. * out again.
  3725. * </ol>
  3726. *
  3727. * <p>Stream versions older than 2 will not have the affix pattern variables
  3728. * <code>posPrefixPattern</code> etc. As a result, they will be initialized
  3729. * to <code>null</code>, which means the affix strings will be taken as
  3730. * literal values. This is exactly what we want, since that corresponds to
  3731. * the pre-version-2 behavior.
  3732. */
  3733. private void readObject(ObjectInputStream stream)
  3734. throws IOException, ClassNotFoundException
  3735. {
  3736. stream.defaultReadObject();
  3737. digitList = new DigitList();
  3738.  
  3739. // We force complete fast-path reinitialization when the instance is
  3740. // deserialized. See clone() comment on fastPathCheckNeeded.
  3741. fastPathCheckNeeded = true;
  3742. isFastPath = false;
  3743. fastPathData = null;
  3744.  
  3745. if (serialVersionOnStream < 4) {
  3746. setRoundingMode(RoundingMode.HALF_EVEN);
  3747. } else {
  3748. setRoundingMode(getRoundingMode());
  3749. }
  3750.  
  3751. // We only need to check the maximum counts because NumberFormat
  3752. // .readObject has already ensured that the maximum is greater than the
  3753. // minimum count.
  3754. if (super.getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||
  3755. super.getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
  3756. throw new InvalidObjectException("Digit count out of range");
  3757. }
  3758. if (serialVersionOnStream < 3) {
  3759. setMaximumIntegerDigits(super.getMaximumIntegerDigits());
  3760. setMinimumIntegerDigits(super.getMinimumIntegerDigits());
  3761. setMaximumFractionDigits(super.getMaximumFractionDigits());
  3762. setMinimumFractionDigits(super.getMinimumFractionDigits());
  3763. }
  3764. if (serialVersionOnStream < 1) {
  3765. // Didn't have exponential fields
  3766. useExponentialNotation = false;
  3767. }
  3768. serialVersionOnStream = currentSerialVersion;
  3769. }
  3770.  
  3771. //----------------------------------------------------------------------
  3772. // INSTANCE VARIABLES
  3773. //----------------------------------------------------------------------
  3774.  
  3775. private transient DigitList digitList = new DigitList();
  3776.  
  3777. /**
  3778. * The symbol used as a prefix when formatting positive numbers, e.g. "+".
  3779. *
  3780. * @serial
  3781. * @see #getPositivePrefix
  3782. */
  3783. private String positivePrefix = "";
  3784.  
  3785. /**
  3786. * The symbol used as a suffix when formatting positive numbers.
  3787. * This is often an empty string.
  3788. *
  3789. * @serial
  3790. * @see #getPositiveSuffix
  3791. */
  3792. private String positiveSuffix = "";
  3793.  
  3794. /**
  3795. * The symbol used as a prefix when formatting negative numbers, e.g. "-".
  3796. *
  3797. * @serial
  3798. * @see #getNegativePrefix
  3799. */
  3800. private String negativePrefix = "-";
  3801.  
  3802. /**
  3803. * The symbol used as a suffix when formatting negative numbers.
  3804. * This is often an empty string.
  3805. *
  3806. * @serial
  3807. * @see #getNegativeSuffix
  3808. */
  3809. private String negativeSuffix = "";
  3810.  
  3811. /**
  3812. * The prefix pattern for non-negative numbers. This variable corresponds
  3813. * to <code>positivePrefix</code>.
  3814. *
  3815. * <p>This pattern is expanded by the method <code>expandAffix()</code> to
  3816. * <code>positivePrefix</code> to update the latter to reflect changes in
  3817. * <code>symbols</code>. If this variable is <code>null</code> then
  3818. * <code>positivePrefix</code> is taken as a literal value that does not
  3819. * change when <code>symbols</code> changes. This variable is always
  3820. * <code>null</code> for <code>DecimalFormat</code> objects older than
  3821. * stream version 2 restored from stream.
  3822. *
  3823. * @serial
  3824. * @since 1.3
  3825. */
  3826. private String posPrefixPattern;
  3827.  
  3828. /**
  3829. * The suffix pattern for non-negative numbers. This variable corresponds
  3830. * to <code>positiveSuffix</code>. This variable is analogous to
  3831. * <code>posPrefixPattern</code>; see that variable for further
  3832. * documentation.
  3833. *
  3834. * @serial
  3835. * @since 1.3
  3836. */
  3837. private String posSuffixPattern;
  3838.  
  3839. /**
  3840. * The prefix pattern for negative numbers. This variable corresponds
  3841. * to <code>negativePrefix</code>. This variable is analogous to
  3842. * <code>posPrefixPattern</code>; see that variable for further
  3843. * documentation.
  3844. *
  3845. * @serial
  3846. * @since 1.3
  3847. */
  3848. private String negPrefixPattern;
  3849.  
  3850. /**
  3851. * The suffix pattern for negative numbers. This variable corresponds
  3852. * to <code>negativeSuffix</code>. This variable is analogous to
  3853. * <code>posPrefixPattern</code>; see that variable for further
  3854. * documentation.
  3855. *
  3856. * @serial
  3857. * @since 1.3
  3858. */
  3859. private String negSuffixPattern;
  3860.  
  3861. /**
  3862. * The multiplier for use in percent, per mille, etc.
  3863. *
  3864. * @serial
  3865. * @see #getMultiplier
  3866. */
  3867. private int multiplier = 1;
  3868.  
  3869. /**
  3870. * The number of digits between grouping separators in the integer
  3871. * portion of a number. Must be greater than 0 if
  3872. * <code>NumberFormat.groupingUsed</code> is true.
  3873. *
  3874. * @serial
  3875. * @see #getGroupingSize
  3876. * @see java.text.NumberFormat#isGroupingUsed
  3877. */
  3878. private byte groupingSize = 3; // invariant, > 0 if useThousands
  3879.  
  3880. /**
  3881. * If true, forces the decimal separator to always appear in a formatted
  3882. * number, even if the fractional part of the number is zero.
  3883. *
  3884. * @serial
  3885. * @see #isDecimalSeparatorAlwaysShown
  3886. */
  3887. private boolean decimalSeparatorAlwaysShown = false;
  3888.  
  3889. /**
  3890. * If true, parse returns BigDecimal wherever possible.
  3891. *
  3892. * @serial
  3893. * @see #isParseBigDecimal
  3894. * @since 1.5
  3895. */
  3896. private boolean parseBigDecimal = false;
  3897.  
  3898. /**
  3899. * True if this object represents a currency format. This determines
  3900. * whether the monetary decimal separator is used instead of the normal one.
  3901. */
  3902. private transient boolean isCurrencyFormat = false;
  3903.  
  3904. /**
  3905. * The <code>DecimalFormatSymbols</code> object used by this format.
  3906. * It contains the symbols used to format numbers, e.g. the grouping separator,
  3907. * decimal separator, and so on.
  3908. *
  3909. * @serial
  3910. * @see #setDecimalFormatSymbols
  3911. * @see java.text.DecimalFormatSymbols
  3912. */
  3913. private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();
  3914.  
  3915. /**
  3916. * True to force the use of exponential (i.e. scientific) notation when formatting
  3917. * numbers.
  3918. *
  3919. * @serial
  3920. * @since 1.2
  3921. */
  3922. private boolean useExponentialNotation; // Newly persistent in the Java 2 platform v.1.2
  3923.  
  3924. /**
  3925. * FieldPositions describing the positive prefix String. This is
  3926. * lazily created. Use <code>getPositivePrefixFieldPositions</code>
  3927. * when needed.
  3928. */
  3929. private transient FieldPosition[] positivePrefixFieldPositions;
  3930.  
  3931. /**
  3932. * FieldPositions describing the positive suffix String. This is
  3933. * lazily created. Use <code>getPositiveSuffixFieldPositions</code>
  3934. * when needed.
  3935. */
  3936. private transient FieldPosition[] positiveSuffixFieldPositions;
  3937.  
  3938. /**
  3939. * FieldPositions describing the negative prefix String. This is
  3940. * lazily created. Use <code>getNegativePrefixFieldPositions</code>
  3941. * when needed.
  3942. */
  3943. private transient FieldPosition[] negativePrefixFieldPositions;
  3944.  
  3945. /**
  3946. * FieldPositions describing the negative suffix String. This is
  3947. * lazily created. Use <code>getNegativeSuffixFieldPositions</code>
  3948. * when needed.
  3949. */
  3950. private transient FieldPosition[] negativeSuffixFieldPositions;
  3951.  
  3952. /**
  3953. * The minimum number of digits used to display the exponent when a number is
  3954. * formatted in exponential notation. This field is ignored if
  3955. * <code>useExponentialNotation</code> is not true.
  3956. *
  3957. * @serial
  3958. * @since 1.2
  3959. */
  3960. private byte minExponentDigits; // Newly persistent in the Java 2 platform v.1.2
  3961.  
  3962. /**
  3963. * The maximum number of digits allowed in the integer portion of a
  3964. * <code>BigInteger</code> or <code>BigDecimal</code> number.
  3965. * <code>maximumIntegerDigits</code> must be greater than or equal to
  3966. * <code>minimumIntegerDigits</code>.
  3967. *
  3968. * @serial
  3969. * @see #getMaximumIntegerDigits
  3970. * @since 1.5
  3971. */
  3972. private int maximumIntegerDigits = super.getMaximumIntegerDigits();
  3973.  
  3974. /**
  3975. * The minimum number of digits allowed in the integer portion of a
  3976. * <code>BigInteger</code> or <code>BigDecimal</code> number.
  3977. * <code>minimumIntegerDigits</code> must be less than or equal to
  3978. * <code>maximumIntegerDigits</code>.
  3979. *
  3980. * @serial
  3981. * @see #getMinimumIntegerDigits
  3982. * @since 1.5
  3983. */
  3984. private int minimumIntegerDigits = super.getMinimumIntegerDigits();
  3985.  
  3986. /**
  3987. * The maximum number of digits allowed in the fractional portion of a
  3988. * <code>BigInteger</code> or <code>BigDecimal</code> number.
  3989. * <code>maximumFractionDigits</code> must be greater than or equal to
  3990. * <code>minimumFractionDigits</code>.
  3991. *
  3992. * @serial
  3993. * @see #getMaximumFractionDigits
  3994. * @since 1.5
  3995. */
  3996. private int maximumFractionDigits = super.getMaximumFractionDigits();
  3997.  
  3998. /**
  3999. * The minimum number of digits allowed in the fractional portion of a
  4000. * <code>BigInteger</code> or <code>BigDecimal</code> number.
  4001. * <code>minimumFractionDigits</code> must be less than or equal to
  4002. * <code>maximumFractionDigits</code>.
  4003. *
  4004. * @serial
  4005. * @see #getMinimumFractionDigits
  4006. * @since 1.5
  4007. */
  4008. private int minimumFractionDigits = super.getMinimumFractionDigits();
  4009.  
  4010. /**
  4011. * The {@link java.math.RoundingMode} used in this DecimalFormat.
  4012. *
  4013. * @serial
  4014. * @since 1.6
  4015. */
  4016. private RoundingMode roundingMode = RoundingMode.HALF_EVEN;
  4017.  
  4018. // ------ DecimalFormat fields for fast-path for double algorithm ------
  4019.  
  4020. /**
  4021. * Helper inner utility class for storing the data used in the fast-path
  4022. * algorithm. Almost all fields related to fast-path are encapsulated in
  4023. * this class.
  4024. *
  4025. * Any {@code DecimalFormat} instance has a {@code fastPathData}
  4026. * reference field that is null unless both the properties of the instance
  4027. * are such that the instance is in the "fast-path" state, and a format call
  4028. * has been done at least once while in this state.
  4029. *
  4030. * Almost all fields are related to the "fast-path" state only and don't
  4031. * change until one of the instance properties is changed.
  4032. *
  4033. * {@code firstUsedIndex} and {@code lastFreeIndex} are the only
  4034. * two fields that are used and modified while inside a call to
  4035. * {@code fastDoubleFormat}.
  4036. *
  4037. */
  4038. private static class FastPathData {
  4039. // --- Temporary fields used in fast-path, shared by several methods.
  4040.  
  4041. /** The first unused index at the end of the formatted result. */
  4042. int lastFreeIndex;
  4043.  
  4044. /** The first used index at the beginning of the formatted result */
  4045. int firstUsedIndex;
  4046.  
  4047. // --- State fields related to fast-path status. Changes due to a
  4048. // property change only. Set by checkAndSetFastPathStatus() only.
  4049.  
  4050. /** Difference between locale zero and default zero representation. */
  4051. int zeroDelta;
  4052.  
  4053. /** Locale char for grouping separator. */
  4054. char groupingChar;
  4055.  
  4056. /** Fixed index position of last integral digit of formatted result */
  4057. int integralLastIndex;
  4058.  
  4059. /** Fixed index position of first fractional digit of formatted result */
  4060. int fractionalFirstIndex;
  4061.  
  4062. /** Fractional constants depending on decimal|currency state */
  4063. double fractionalScaleFactor;
  4064. int fractionalMaxIntBound;
  4065.  
  4066. /** The char array buffer that will contain the formatted result */
  4067. char[] fastPathContainer;
  4068.  
  4069. /** Suffixes recorded as char array for efficiency. */
  4070. char[] charsPositivePrefix;
  4071. char[] charsNegativePrefix;
  4072. char[] charsPositiveSuffix;
  4073. char[] charsNegativeSuffix;
  4074. boolean positiveAffixesRequired = true;
  4075. boolean negativeAffixesRequired = true;
  4076. }
  4077.  
  4078. /** The format fast-path status of the instance. Logical state. */
  4079. private transient boolean isFastPath = false;
  4080.  
  4081. /** Flag stating need of check and reinit fast-path status on next format call. */
  4082. private transient boolean fastPathCheckNeeded = true;
  4083.  
  4084. /** DecimalFormat reference to its FastPathData */
  4085. private transient FastPathData fastPathData;
  4086.  
  4087. //----------------------------------------------------------------------
  4088.  
  4089. static final int currentSerialVersion = 4;
  4090.  
  4091. /**
  4092. * The internal serial version which says which version was written.
  4093. * Possible values are:
  4094. * <ul>
  4095. * <li><b>0</b> (default): versions before the Java 2 platform v1.2
  4096. * <li><b>1</b>: version for 1.2, which includes the two new fields
  4097. * <code>useExponentialNotation</code> and
  4098. * <code>minExponentDigits</code>.
  4099. * <li><b>2</b>: version for 1.3 and later, which adds four new fields:
  4100. * <code>posPrefixPattern</code>, <code>posSuffixPattern</code>,
  4101. * <code>negPrefixPattern</code>, and <code>negSuffixPattern</code>.
  4102. * <li><b>3</b>: version for 1.5 and later, which adds five new fields:
  4103. * <code>maximumIntegerDigits</code>,
  4104. * <code>minimumIntegerDigits</code>,
  4105. * <code>maximumFractionDigits</code>,
  4106. * <code>minimumFractionDigits</code>, and
  4107. * <code>parseBigDecimal</code>.
  4108. * <li><b>4</b>: version for 1.6 and later, which adds one new field:
  4109. * <code>roundingMode</code>.
  4110. * </ul>
  4111. * @since 1.2
  4112. * @serial
  4113. */
  4114. private int serialVersionOnStream = currentSerialVersion;
  4115.  
  4116. //----------------------------------------------------------------------
  4117. // CONSTANTS
  4118. //----------------------------------------------------------------------
  4119.  
  4120. // ------ Fast-Path for double Constants ------
  4121.  
  4122. /** Maximum valid integer value for applying fast-path algorithm */
  4123. private static final double MAX_INT_AS_DOUBLE = (double) Integer.MAX_VALUE;
  4124.  
  4125. /**
  4126. * The digit arrays used in the fast-path methods for collecting digits.
  4127. * Using 3 constants arrays of chars ensures a very fast collection of digits
  4128. */
  4129. private static class DigitArrays {
  4130. static final char[] DigitOnes1000 = new char[1000];
  4131. static final char[] DigitTens1000 = new char[1000];
  4132. static final char[] DigitHundreds1000 = new char[1000];
  4133.  
  4134. // initialize on demand holder class idiom for arrays of digits
  4135. static {
  4136. int tenIndex = 0;
  4137. int hundredIndex = 0;
  4138. char digitOne = '0';
  4139. char digitTen = '0';
  4140. char digitHundred = '0';
  4141. for (int i = 0; i < 1000; i++ ) {
  4142.  
  4143. DigitOnes1000[i] = digitOne;
  4144. if (digitOne == '9')
  4145. digitOne = '0';
  4146. else
  4147. digitOne++;
  4148.  
  4149. DigitTens1000[i] = digitTen;
  4150. if (i == (tenIndex + 9)) {
  4151. tenIndex += 10;
  4152. if (digitTen == '9')
  4153. digitTen = '0';
  4154. else
  4155. digitTen++;
  4156. }
  4157.  
  4158. DigitHundreds1000[i] = digitHundred;
  4159. if (i == (hundredIndex + 99)) {
  4160. digitHundred++;
  4161. hundredIndex += 100;
  4162. }
  4163. }
  4164. }
  4165. }
  4166. // ------ Fast-Path for double Constants end ------
  4167.  
  4168. // Constants for characters used in programmatic (unlocalized) patterns.
  4169. private static final char PATTERN_ZERO_DIGIT = '0';
  4170. private static final char PATTERN_GROUPING_SEPARATOR = ',';
  4171. private static final char PATTERN_DECIMAL_SEPARATOR = '.';
  4172. private static final char PATTERN_PER_MILLE = '\u2030';
  4173. private static final char PATTERN_PERCENT = '%';
  4174. private static final char PATTERN_DIGIT = '#';
  4175. private static final char PATTERN_SEPARATOR = ';';
  4176. private static final String PATTERN_EXPONENT = "E";
  4177. private static final char PATTERN_MINUS = '-';
  4178.  
  4179. /**
  4180. * The CURRENCY_SIGN is the standard Unicode symbol for currency. It
  4181. * is used in patterns and substituted with either the currency symbol,
  4182. * or if it is doubled, with the international currency symbol. If the
  4183. * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
  4184. * replaced with the monetary decimal separator.
  4185. *
  4186. * The CURRENCY_SIGN is not localized.
  4187. */
  4188. private static final char CURRENCY_SIGN = '\u00A4';
  4189.  
  4190. private static final char QUOTE = '\'';
  4191.  
  4192. private static FieldPosition[] EmptyFieldPositionArray = new FieldPosition[0];
  4193.  
  4194. // Upper limit on integer and fraction digits for a Java double
  4195. static final int DOUBLE_INTEGER_DIGITS = 309;
  4196. static final int DOUBLE_FRACTION_DIGITS = 340;
  4197.  
  4198. // Upper limit on integer and fraction digits for BigDecimal and BigInteger
  4199. static final int MAXIMUM_INTEGER_DIGITS = Integer.MAX_VALUE;
  4200. static final int MAXIMUM_FRACTION_DIGITS = Integer.MAX_VALUE;
  4201.  
  4202. // Proclaim JDK 1.1 serial compatibility.
  4203. static final long serialVersionUID = 864413376551465018L;
  4204. }

DecimalFormat详解的更多相关文章

  1. BigDecimal的用法详解(保留两位小数,四舍五入,数字格式化,科学计数法转数字,数字里的逗号处理)

    转自:https://blog.csdn.net/ochangwen/article/details/51531866 一.简介 Java在java.math包中提供的API类BigDecimal,用 ...

  2. 详解JMeter函数和变量(转载)

    详解JMeter函数和变量(1) JMeter函数可以被认为是某种特殊的变量,它们可以被采样器或者其他测试元件所引用.函数调用的语法如下: ${__functionName(var1,var2,var ...

  3. jmeter--函数助手对话框之参数详解

    详解JMeter函数和变量 测试人员可以在JMeter的选项菜单中找到函数助手对话框("Function Helper"对话框),如图11-1所示. 图11-1 函数助手(Func ...

  4. Java之BigDecimal详解

    一.BigDecimal概述 ​ Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.双精度浮点型变量double可以处理16位有效数,但在实 ...

  5. 在java poi导入Excel通用工具类示例详解

    转: 在java poi导入Excel通用工具类示例详解 更新时间:2017年09月10日 14:21:36   作者:daochuwenziyao   我要评论   这篇文章主要给大家介绍了关于在j ...

  6. Jmeter(八) - 从入门到精通 - JMeter配置元件(详解教程)

    1.简介 JMeter配置元件可以用来初始化默认值和变量,读取文件数据,设置公共请求参数,赋予变量值等,以便后续采样器使用.将在其作用域的初始化阶段处理.配置元件(Config Element)提供对 ...

  7. hive beeline详解

    Hive客户端工具后续将使用Beeline 替代HiveCLI ,并且后续版本也会废弃掉HiveCLI 客户端工具,Beeline是 Hive 0.11版本引入的新命令行客户端工具,它是基于SQLLi ...

  8. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  9. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

随机推荐

  1. 阻塞式I/O实现简单TCP通信

    一.技术简介 (1)服务端打开两个端口9999和6666监听外来连接: (2)服务端的子进程通过端口9999监听外来消息,通过端口6666发送消息: (3)客户端的子进程处理外来消息,父进程发送消息 ...

  2. mysql单表删除记录DELETE

    DELETE FROM tbl_name  [WHERE where_condition] mysql> SELECT * FROM users;+----+----------+------- ...

  3. sql leetcode -Duplicate Emails

    第一种解法: select distinct p1.Email as Email from Person p1, Person p2 where p1.Email=p2.Email and p1.Id ...

  4. Empirical Evaluation of Speaker Adaptation on DNN based Acoustic Model

    DNN声学模型说话人自适应的经验性评估 年3月27日 发表于:Sound (cs.SD); Computation and Language (cs.CL); Audio and Speech Pro ...

  5. 【vue】中 $listeners 的使用方法

    $listeners 的官方介绍: 包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器.它可以通过 v-on="$listeners" 传入内部组件——在 ...

  6. 实现两线程的同步一(wait/notify)

    1.使用Object的wait和notify public class WaitAndNotifyDemo { public static void main(String[] args) throw ...

  7. mysql库文件操作:

    增 :  create database db1 charset utf8; 查询:  当前创建的库  show create database db1; 所有:  show databases; 改 ...

  8. js 关键字 in 的使用方法

    参考地址:http://www.cnblogs.com/qiantuwuliang/archive/2011/01/08/1930643.html in 操作符用于确定某个元素是否在数组中,判断某个属 ...

  9. Javascript入门(五)数组操作、循环语句

    一.数组与数组操作 <script type="text/javascript"> //数组定义方式 var list1 = new Array(1,2,3); var ...

  10. SQL攻击-预编译--缓存

    PreparedStatement l 它是Statement接口的子接口: l 强大之处: 防SQL攻击: 提高代码的可读性.可维护性: 提高效率! l 学习PreparedStatement的用法 ...