|
1 /* |
|
2 * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Oracle designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Oracle in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 * or visit www.oracle.com if you need additional information or have any |
|
23 * questions. |
|
24 */ |
|
25 |
|
26 /* |
|
27 * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved |
|
28 * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved |
|
29 * |
|
30 * The original version of this source code and documentation is copyrighted |
|
31 * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These |
|
32 * materials are provided under terms of a License Agreement between Taligent |
|
33 * and Sun. This technology is protected by multiple US and International |
|
34 * patents. This notice and attribution to Taligent may not be removed. |
|
35 * Taligent is a registered trademark of Taligent, Inc. |
|
36 * |
|
37 */ |
|
38 |
|
39 package java.text; |
|
40 |
|
41 import java.math.BigDecimal; |
|
42 import java.math.BigInteger; |
|
43 import java.math.RoundingMode; |
|
44 import jdk.internal.math.FloatingDecimal; |
|
45 |
|
46 /** |
|
47 * Digit List. Private to DecimalFormat. |
|
48 * Handles the transcoding |
|
49 * between numeric values and strings of characters. Only handles |
|
50 * non-negative numbers. The division of labor between DigitList and |
|
51 * DecimalFormat is that DigitList handles the radix 10 representation |
|
52 * issues; DecimalFormat handles the locale-specific issues such as |
|
53 * positive/negative, grouping, decimal point, currency, and so on. |
|
54 * |
|
55 * A DigitList is really a representation of a floating point value. |
|
56 * It may be an integer value; we assume that a double has sufficient |
|
57 * precision to represent all digits of a long. |
|
58 * |
|
59 * The DigitList representation consists of a string of characters, |
|
60 * which are the digits radix 10, from '0' to '9'. It also has a radix |
|
61 * 10 exponent associated with it. The value represented by a DigitList |
|
62 * object can be computed by mulitplying the fraction f, where 0 <= f < 1, |
|
63 * derived by placing all the digits of the list to the right of the |
|
64 * decimal point, by 10^exponent. |
|
65 * |
|
66 * @see Locale |
|
67 * @see Format |
|
68 * @see NumberFormat |
|
69 * @see DecimalFormat |
|
70 * @see ChoiceFormat |
|
71 * @see MessageFormat |
|
72 * @author Mark Davis, Alan Liu |
|
73 */ |
|
74 final class DigitList implements Cloneable { |
|
75 /** |
|
76 * The maximum number of significant digits in an IEEE 754 double, that |
|
77 * is, in a Java double. This must not be increased, or garbage digits |
|
78 * will be generated, and should not be decreased, or accuracy will be lost. |
|
79 */ |
|
80 public static final int MAX_COUNT = 19; // == Long.toString(Long.MAX_VALUE).length() |
|
81 |
|
82 /** |
|
83 * These data members are intentionally public and can be set directly. |
|
84 * |
|
85 * The value represented is given by placing the decimal point before |
|
86 * digits[decimalAt]. If decimalAt is < 0, then leading zeros between |
|
87 * the decimal point and the first nonzero digit are implied. If decimalAt |
|
88 * is > count, then trailing zeros between the digits[count-1] and the |
|
89 * decimal point are implied. |
|
90 * |
|
91 * Equivalently, the represented value is given by f * 10^decimalAt. Here |
|
92 * f is a value 0.1 <= f < 1 arrived at by placing the digits in Digits to |
|
93 * the right of the decimal. |
|
94 * |
|
95 * DigitList is normalized, so if it is non-zero, figits[0] is non-zero. We |
|
96 * don't allow denormalized numbers because our exponent is effectively of |
|
97 * unlimited magnitude. The count value contains the number of significant |
|
98 * digits present in digits[]. |
|
99 * |
|
100 * Zero is represented by any DigitList with count == 0 or with each digits[i] |
|
101 * for all i <= count == '0'. |
|
102 */ |
|
103 public int decimalAt = 0; |
|
104 public int count = 0; |
|
105 public char[] digits = new char[MAX_COUNT]; |
|
106 |
|
107 private char[] data; |
|
108 private RoundingMode roundingMode = RoundingMode.HALF_EVEN; |
|
109 private boolean isNegative = false; |
|
110 |
|
111 /** |
|
112 * Return true if the represented number is zero. |
|
113 */ |
|
114 boolean isZero() { |
|
115 for (int i=0; i < count; ++i) { |
|
116 if (digits[i] != '0') { |
|
117 return false; |
|
118 } |
|
119 } |
|
120 return true; |
|
121 } |
|
122 |
|
123 /** |
|
124 * Set the rounding mode |
|
125 */ |
|
126 void setRoundingMode(RoundingMode r) { |
|
127 roundingMode = r; |
|
128 } |
|
129 |
|
130 /** |
|
131 * Clears out the digits. |
|
132 * Use before appending them. |
|
133 * Typically, you set a series of digits with append, then at the point |
|
134 * you hit the decimal point, you set myDigitList.decimalAt = myDigitList.count; |
|
135 * then go on appending digits. |
|
136 */ |
|
137 public void clear () { |
|
138 decimalAt = 0; |
|
139 count = 0; |
|
140 } |
|
141 |
|
142 /** |
|
143 * Appends a digit to the list, extending the list when necessary. |
|
144 */ |
|
145 public void append(char digit) { |
|
146 if (count == digits.length) { |
|
147 char[] data = new char[count + 100]; |
|
148 System.arraycopy(digits, 0, data, 0, count); |
|
149 digits = data; |
|
150 } |
|
151 digits[count++] = digit; |
|
152 } |
|
153 |
|
154 /** |
|
155 * Utility routine to get the value of the digit list |
|
156 * If (count == 0) this throws a NumberFormatException, which |
|
157 * mimics Long.parseLong(). |
|
158 */ |
|
159 public final double getDouble() { |
|
160 if (count == 0) { |
|
161 return 0.0; |
|
162 } |
|
163 |
|
164 StringBuffer temp = getStringBuffer(); |
|
165 temp.append('.'); |
|
166 temp.append(digits, 0, count); |
|
167 temp.append('E'); |
|
168 temp.append(decimalAt); |
|
169 return Double.parseDouble(temp.toString()); |
|
170 } |
|
171 |
|
172 /** |
|
173 * Utility routine to get the value of the digit list. |
|
174 * If (count == 0) this returns 0, unlike Long.parseLong(). |
|
175 */ |
|
176 public final long getLong() { |
|
177 // for now, simple implementation; later, do proper IEEE native stuff |
|
178 |
|
179 if (count == 0) { |
|
180 return 0; |
|
181 } |
|
182 |
|
183 // We have to check for this, because this is the one NEGATIVE value |
|
184 // we represent. If we tried to just pass the digits off to parseLong, |
|
185 // we'd get a parse failure. |
|
186 if (isLongMIN_VALUE()) { |
|
187 return Long.MIN_VALUE; |
|
188 } |
|
189 |
|
190 StringBuffer temp = getStringBuffer(); |
|
191 temp.append(digits, 0, count); |
|
192 for (int i = count; i < decimalAt; ++i) { |
|
193 temp.append('0'); |
|
194 } |
|
195 return Long.parseLong(temp.toString()); |
|
196 } |
|
197 |
|
198 public final BigDecimal getBigDecimal() { |
|
199 if (count == 0) { |
|
200 if (decimalAt == 0) { |
|
201 return BigDecimal.ZERO; |
|
202 } else { |
|
203 return new BigDecimal("0E" + decimalAt); |
|
204 } |
|
205 } |
|
206 |
|
207 if (decimalAt == count) { |
|
208 return new BigDecimal(digits, 0, count); |
|
209 } else { |
|
210 return new BigDecimal(digits, 0, count).scaleByPowerOfTen(decimalAt - count); |
|
211 } |
|
212 } |
|
213 |
|
214 /** |
|
215 * Return true if the number represented by this object can fit into |
|
216 * a long. |
|
217 * @param isPositive true if this number should be regarded as positive |
|
218 * @param ignoreNegativeZero true if -0 should be regarded as identical to |
|
219 * +0; otherwise they are considered distinct |
|
220 * @return true if this number fits into a Java long |
|
221 */ |
|
222 boolean fitsIntoLong(boolean isPositive, boolean ignoreNegativeZero) { |
|
223 // Figure out if the result will fit in a long. We have to |
|
224 // first look for nonzero digits after the decimal point; |
|
225 // then check the size. If the digit count is 18 or less, then |
|
226 // the value can definitely be represented as a long. If it is 19 |
|
227 // then it may be too large. |
|
228 |
|
229 // Trim trailing zeros. This does not change the represented value. |
|
230 while (count > 0 && digits[count - 1] == '0') { |
|
231 --count; |
|
232 } |
|
233 |
|
234 if (count == 0) { |
|
235 // Positive zero fits into a long, but negative zero can only |
|
236 // be represented as a double. - bug 4162852 |
|
237 return isPositive || ignoreNegativeZero; |
|
238 } |
|
239 |
|
240 if (decimalAt < count || decimalAt > MAX_COUNT) { |
|
241 return false; |
|
242 } |
|
243 |
|
244 if (decimalAt < MAX_COUNT) return true; |
|
245 |
|
246 // At this point we have decimalAt == count, and count == MAX_COUNT. |
|
247 // The number will overflow if it is larger than 9223372036854775807 |
|
248 // or smaller than -9223372036854775808. |
|
249 for (int i=0; i<count; ++i) { |
|
250 char dig = digits[i], max = LONG_MIN_REP[i]; |
|
251 if (dig > max) return false; |
|
252 if (dig < max) return true; |
|
253 } |
|
254 |
|
255 // At this point the first count digits match. If decimalAt is less |
|
256 // than count, then the remaining digits are zero, and we return true. |
|
257 if (count < decimalAt) return true; |
|
258 |
|
259 // Now we have a representation of Long.MIN_VALUE, without the leading |
|
260 // negative sign. If this represents a positive value, then it does |
|
261 // not fit; otherwise it fits. |
|
262 return !isPositive; |
|
263 } |
|
264 |
|
265 /** |
|
266 * Set the digit list to a representation of the given double value. |
|
267 * This method supports fixed-point notation. |
|
268 * @param isNegative Boolean value indicating whether the number is negative. |
|
269 * @param source Value to be converted; must not be Inf, -Inf, Nan, |
|
270 * or a value <= 0. |
|
271 * @param maximumFractionDigits The most fractional digits which should |
|
272 * be converted. |
|
273 */ |
|
274 final void set(boolean isNegative, double source, int maximumFractionDigits) { |
|
275 set(isNegative, source, maximumFractionDigits, true); |
|
276 } |
|
277 |
|
278 /** |
|
279 * Set the digit list to a representation of the given double value. |
|
280 * This method supports both fixed-point and exponential notation. |
|
281 * @param isNegative Boolean value indicating whether the number is negative. |
|
282 * @param source Value to be converted; must not be Inf, -Inf, Nan, |
|
283 * or a value <= 0. |
|
284 * @param maximumDigits The most fractional or total digits which should |
|
285 * be converted. |
|
286 * @param fixedPoint If true, then maximumDigits is the maximum |
|
287 * fractional digits to be converted. If false, total digits. |
|
288 */ |
|
289 final void set(boolean isNegative, double source, int maximumDigits, boolean fixedPoint) { |
|
290 |
|
291 FloatingDecimal.BinaryToASCIIConverter fdConverter = FloatingDecimal.getBinaryToASCIIConverter(source); |
|
292 boolean hasBeenRoundedUp = fdConverter.digitsRoundedUp(); |
|
293 boolean valueExactAsDecimal = fdConverter.decimalDigitsExact(); |
|
294 assert !fdConverter.isExceptional(); |
|
295 String digitsString = fdConverter.toJavaFormatString(); |
|
296 |
|
297 set(isNegative, digitsString, |
|
298 hasBeenRoundedUp, valueExactAsDecimal, |
|
299 maximumDigits, fixedPoint); |
|
300 } |
|
301 |
|
302 /** |
|
303 * Generate a representation of the form DDDDD, DDDDD.DDDDD, or |
|
304 * DDDDDE+/-DDDDD. |
|
305 * @param roundedUp whether or not rounding up has already happened. |
|
306 * @param valueExactAsDecimal whether or not collected digits provide |
|
307 * an exact decimal representation of the value. |
|
308 */ |
|
309 private void set(boolean isNegative, String s, |
|
310 boolean roundedUp, boolean valueExactAsDecimal, |
|
311 int maximumDigits, boolean fixedPoint) { |
|
312 |
|
313 this.isNegative = isNegative; |
|
314 int len = s.length(); |
|
315 char[] source = getDataChars(len); |
|
316 s.getChars(0, len, source, 0); |
|
317 |
|
318 decimalAt = -1; |
|
319 count = 0; |
|
320 int exponent = 0; |
|
321 // Number of zeros between decimal point and first non-zero digit after |
|
322 // decimal point, for numbers < 1. |
|
323 int leadingZerosAfterDecimal = 0; |
|
324 boolean nonZeroDigitSeen = false; |
|
325 |
|
326 for (int i = 0; i < len; ) { |
|
327 char c = source[i++]; |
|
328 if (c == '.') { |
|
329 decimalAt = count; |
|
330 } else if (c == 'e' || c == 'E') { |
|
331 exponent = parseInt(source, i, len); |
|
332 break; |
|
333 } else { |
|
334 if (!nonZeroDigitSeen) { |
|
335 nonZeroDigitSeen = (c != '0'); |
|
336 if (!nonZeroDigitSeen && decimalAt != -1) |
|
337 ++leadingZerosAfterDecimal; |
|
338 } |
|
339 if (nonZeroDigitSeen) { |
|
340 digits[count++] = c; |
|
341 } |
|
342 } |
|
343 } |
|
344 if (decimalAt == -1) { |
|
345 decimalAt = count; |
|
346 } |
|
347 if (nonZeroDigitSeen) { |
|
348 decimalAt += exponent - leadingZerosAfterDecimal; |
|
349 } |
|
350 |
|
351 if (fixedPoint) { |
|
352 // The negative of the exponent represents the number of leading |
|
353 // zeros between the decimal and the first non-zero digit, for |
|
354 // a value < 0.1 (e.g., for 0.00123, -decimalAt == 2). If this |
|
355 // is more than the maximum fraction digits, then we have an underflow |
|
356 // for the printed representation. |
|
357 if (-decimalAt > maximumDigits) { |
|
358 // Handle an underflow to zero when we round something like |
|
359 // 0.0009 to 2 fractional digits. |
|
360 count = 0; |
|
361 return; |
|
362 } else if (-decimalAt == maximumDigits) { |
|
363 // If we round 0.0009 to 3 fractional digits, then we have to |
|
364 // create a new one digit in the least significant location. |
|
365 if (shouldRoundUp(0, roundedUp, valueExactAsDecimal)) { |
|
366 count = 1; |
|
367 ++decimalAt; |
|
368 digits[0] = '1'; |
|
369 } else { |
|
370 count = 0; |
|
371 } |
|
372 return; |
|
373 } |
|
374 // else fall through |
|
375 } |
|
376 |
|
377 // Eliminate trailing zeros. |
|
378 while (count > 1 && digits[count - 1] == '0') { |
|
379 --count; |
|
380 } |
|
381 |
|
382 // Eliminate digits beyond maximum digits to be displayed. |
|
383 // Round up if appropriate. |
|
384 round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits, |
|
385 roundedUp, valueExactAsDecimal); |
|
386 |
|
387 } |
|
388 |
|
389 /** |
|
390 * Round the representation to the given number of digits. |
|
391 * @param maximumDigits The maximum number of digits to be shown. |
|
392 * @param alreadyRounded whether or not rounding up has already happened. |
|
393 * @param valueExactAsDecimal whether or not collected digits provide |
|
394 * an exact decimal representation of the value. |
|
395 * |
|
396 * Upon return, count will be less than or equal to maximumDigits. |
|
397 */ |
|
398 private final void round(int maximumDigits, |
|
399 boolean alreadyRounded, |
|
400 boolean valueExactAsDecimal) { |
|
401 // Eliminate digits beyond maximum digits to be displayed. |
|
402 // Round up if appropriate. |
|
403 if (maximumDigits >= 0 && maximumDigits < count) { |
|
404 if (shouldRoundUp(maximumDigits, alreadyRounded, valueExactAsDecimal)) { |
|
405 // Rounding up involved incrementing digits from LSD to MSD. |
|
406 // In most cases this is simple, but in a worst case situation |
|
407 // (9999..99) we have to adjust the decimalAt value. |
|
408 for (;;) { |
|
409 --maximumDigits; |
|
410 if (maximumDigits < 0) { |
|
411 // We have all 9's, so we increment to a single digit |
|
412 // of one and adjust the exponent. |
|
413 digits[0] = '1'; |
|
414 ++decimalAt; |
|
415 maximumDigits = 0; // Adjust the count |
|
416 break; |
|
417 } |
|
418 |
|
419 ++digits[maximumDigits]; |
|
420 if (digits[maximumDigits] <= '9') break; |
|
421 // digits[maximumDigits] = '0'; // Unnecessary since we'll truncate this |
|
422 } |
|
423 ++maximumDigits; // Increment for use as count |
|
424 } |
|
425 count = maximumDigits; |
|
426 |
|
427 // Eliminate trailing zeros. |
|
428 while (count > 1 && digits[count-1] == '0') { |
|
429 --count; |
|
430 } |
|
431 } |
|
432 } |
|
433 |
|
434 |
|
435 /** |
|
436 * Return true if truncating the representation to the given number |
|
437 * of digits will result in an increment to the last digit. This |
|
438 * method implements the rounding modes defined in the |
|
439 * java.math.RoundingMode class. |
|
440 * [bnf] |
|
441 * @param maximumDigits the number of digits to keep, from 0 to |
|
442 * <code>count-1</code>. If 0, then all digits are rounded away, and |
|
443 * this method returns true if a one should be generated (e.g., formatting |
|
444 * 0.09 with "#.#"). |
|
445 * @param alreadyRounded whether or not rounding up has already happened. |
|
446 * @param valueExactAsDecimal whether or not collected digits provide |
|
447 * an exact decimal representation of the value. |
|
448 * @exception ArithmeticException if rounding is needed with rounding |
|
449 * mode being set to RoundingMode.UNNECESSARY |
|
450 * @return true if digit <code>maximumDigits-1</code> should be |
|
451 * incremented |
|
452 */ |
|
453 private boolean shouldRoundUp(int maximumDigits, |
|
454 boolean alreadyRounded, |
|
455 boolean valueExactAsDecimal) { |
|
456 if (maximumDigits < count) { |
|
457 /* |
|
458 * To avoid erroneous double-rounding or truncation when converting |
|
459 * a binary double value to text, information about the exactness |
|
460 * of the conversion result in FloatingDecimal, as well as any |
|
461 * rounding done, is needed in this class. |
|
462 * |
|
463 * - For the HALF_DOWN, HALF_EVEN, HALF_UP rounding rules below: |
|
464 * In the case of formating float or double, We must take into |
|
465 * account what FloatingDecimal has done in the binary to decimal |
|
466 * conversion. |
|
467 * |
|
468 * Considering the tie cases, FloatingDecimal may round up the |
|
469 * value (returning decimal digits equal to tie when it is below), |
|
470 * or "truncate" the value to the tie while value is above it, |
|
471 * or provide the exact decimal digits when the binary value can be |
|
472 * converted exactly to its decimal representation given formating |
|
473 * rules of FloatingDecimal ( we have thus an exact decimal |
|
474 * representation of the binary value). |
|
475 * |
|
476 * - If the double binary value was converted exactly as a decimal |
|
477 * value, then DigitList code must apply the expected rounding |
|
478 * rule. |
|
479 * |
|
480 * - If FloatingDecimal already rounded up the decimal value, |
|
481 * DigitList should neither round up the value again in any of |
|
482 * the three rounding modes above. |
|
483 * |
|
484 * - If FloatingDecimal has truncated the decimal value to |
|
485 * an ending '5' digit, DigitList should round up the value in |
|
486 * all of the three rounding modes above. |
|
487 * |
|
488 * |
|
489 * This has to be considered only if digit at maximumDigits index |
|
490 * is exactly the last one in the set of digits, otherwise there are |
|
491 * remaining digits after that position and we don't have to consider |
|
492 * what FloatingDecimal did. |
|
493 * |
|
494 * - Other rounding modes are not impacted by these tie cases. |
|
495 * |
|
496 * - For other numbers that are always converted to exact digits |
|
497 * (like BigInteger, Long, ...), the passed alreadyRounded boolean |
|
498 * have to be set to false, and valueExactAsDecimal has to be set to |
|
499 * true in the upper DigitList call stack, providing the right state |
|
500 * for those situations.. |
|
501 */ |
|
502 |
|
503 switch(roundingMode) { |
|
504 case UP: |
|
505 for (int i=maximumDigits; i<count; ++i) { |
|
506 if (digits[i] != '0') { |
|
507 return true; |
|
508 } |
|
509 } |
|
510 break; |
|
511 case DOWN: |
|
512 break; |
|
513 case CEILING: |
|
514 for (int i=maximumDigits; i<count; ++i) { |
|
515 if (digits[i] != '0') { |
|
516 return !isNegative; |
|
517 } |
|
518 } |
|
519 break; |
|
520 case FLOOR: |
|
521 for (int i=maximumDigits; i<count; ++i) { |
|
522 if (digits[i] != '0') { |
|
523 return isNegative; |
|
524 } |
|
525 } |
|
526 break; |
|
527 case HALF_UP: |
|
528 case HALF_DOWN: |
|
529 if (digits[maximumDigits] > '5') { |
|
530 // Value is above tie ==> must round up |
|
531 return true; |
|
532 } else if (digits[maximumDigits] == '5') { |
|
533 // Digit at rounding position is a '5'. Tie cases. |
|
534 if (maximumDigits != (count - 1)) { |
|
535 // There are remaining digits. Above tie => must round up |
|
536 return true; |
|
537 } else { |
|
538 // Digit at rounding position is the last one ! |
|
539 if (valueExactAsDecimal) { |
|
540 // Exact binary representation. On the tie. |
|
541 // Apply rounding given by roundingMode. |
|
542 return roundingMode == RoundingMode.HALF_UP; |
|
543 } else { |
|
544 // Not an exact binary representation. |
|
545 // Digit sequence either rounded up or truncated. |
|
546 // Round up only if it was truncated. |
|
547 return !alreadyRounded; |
|
548 } |
|
549 } |
|
550 } |
|
551 // Digit at rounding position is < '5' ==> no round up. |
|
552 // Just let do the default, which is no round up (thus break). |
|
553 break; |
|
554 case HALF_EVEN: |
|
555 // Implement IEEE half-even rounding |
|
556 if (digits[maximumDigits] > '5') { |
|
557 return true; |
|
558 } else if (digits[maximumDigits] == '5' ) { |
|
559 if (maximumDigits == (count - 1)) { |
|
560 // the rounding position is exactly the last index : |
|
561 if (alreadyRounded) |
|
562 // If FloatingDecimal rounded up (value was below tie), |
|
563 // then we should not round up again. |
|
564 return false; |
|
565 |
|
566 if (!valueExactAsDecimal) |
|
567 // Otherwise if the digits don't represent exact value, |
|
568 // value was above tie and FloatingDecimal truncated |
|
569 // digits to tie. We must round up. |
|
570 return true; |
|
571 else { |
|
572 // This is an exact tie value, and FloatingDecimal |
|
573 // provided all of the exact digits. We thus apply |
|
574 // HALF_EVEN rounding rule. |
|
575 return ((maximumDigits > 0) && |
|
576 (digits[maximumDigits-1] % 2 != 0)); |
|
577 } |
|
578 } else { |
|
579 // Rounds up if it gives a non null digit after '5' |
|
580 for (int i=maximumDigits+1; i<count; ++i) { |
|
581 if (digits[i] != '0') |
|
582 return true; |
|
583 } |
|
584 } |
|
585 } |
|
586 break; |
|
587 case UNNECESSARY: |
|
588 for (int i=maximumDigits; i<count; ++i) { |
|
589 if (digits[i] != '0') { |
|
590 throw new ArithmeticException( |
|
591 "Rounding needed with the rounding mode being set to RoundingMode.UNNECESSARY"); |
|
592 } |
|
593 } |
|
594 break; |
|
595 default: |
|
596 assert false; |
|
597 } |
|
598 } |
|
599 return false; |
|
600 } |
|
601 |
|
602 /** |
|
603 * Utility routine to set the value of the digit list from a long |
|
604 */ |
|
605 final void set(boolean isNegative, long source) { |
|
606 set(isNegative, source, 0); |
|
607 } |
|
608 |
|
609 /** |
|
610 * Set the digit list to a representation of the given long value. |
|
611 * @param isNegative Boolean value indicating whether the number is negative. |
|
612 * @param source Value to be converted; must be >= 0 or == |
|
613 * Long.MIN_VALUE. |
|
614 * @param maximumDigits The most digits which should be converted. |
|
615 * If maximumDigits is lower than the number of significant digits |
|
616 * in source, the representation will be rounded. Ignored if <= 0. |
|
617 */ |
|
618 final void set(boolean isNegative, long source, int maximumDigits) { |
|
619 this.isNegative = isNegative; |
|
620 |
|
621 // This method does not expect a negative number. However, |
|
622 // "source" can be a Long.MIN_VALUE (-9223372036854775808), |
|
623 // if the number being formatted is a Long.MIN_VALUE. In that |
|
624 // case, it will be formatted as -Long.MIN_VALUE, a number |
|
625 // which is outside the legal range of a long, but which can |
|
626 // be represented by DigitList. |
|
627 if (source <= 0) { |
|
628 if (source == Long.MIN_VALUE) { |
|
629 decimalAt = count = MAX_COUNT; |
|
630 System.arraycopy(LONG_MIN_REP, 0, digits, 0, count); |
|
631 } else { |
|
632 decimalAt = count = 0; // Values <= 0 format as zero |
|
633 } |
|
634 } else { |
|
635 // Rewritten to improve performance. I used to call |
|
636 // Long.toString(), which was about 4x slower than this code. |
|
637 int left = MAX_COUNT; |
|
638 int right; |
|
639 while (source > 0) { |
|
640 digits[--left] = (char)('0' + (source % 10)); |
|
641 source /= 10; |
|
642 } |
|
643 decimalAt = MAX_COUNT - left; |
|
644 // Don't copy trailing zeros. We are guaranteed that there is at |
|
645 // least one non-zero digit, so we don't have to check lower bounds. |
|
646 for (right = MAX_COUNT - 1; digits[right] == '0'; --right) |
|
647 ; |
|
648 count = right - left + 1; |
|
649 System.arraycopy(digits, left, digits, 0, count); |
|
650 } |
|
651 if (maximumDigits > 0) round(maximumDigits, false, true); |
|
652 } |
|
653 |
|
654 /** |
|
655 * Set the digit list to a representation of the given BigDecimal value. |
|
656 * This method supports both fixed-point and exponential notation. |
|
657 * @param isNegative Boolean value indicating whether the number is negative. |
|
658 * @param source Value to be converted; must not be a value <= 0. |
|
659 * @param maximumDigits The most fractional or total digits which should |
|
660 * be converted. |
|
661 * @param fixedPoint If true, then maximumDigits is the maximum |
|
662 * fractional digits to be converted. If false, total digits. |
|
663 */ |
|
664 final void set(boolean isNegative, BigDecimal source, int maximumDigits, boolean fixedPoint) { |
|
665 String s = source.toString(); |
|
666 extendDigits(s.length()); |
|
667 |
|
668 set(isNegative, s, |
|
669 false, true, |
|
670 maximumDigits, fixedPoint); |
|
671 } |
|
672 |
|
673 /** |
|
674 * Set the digit list to a representation of the given BigInteger value. |
|
675 * @param isNegative Boolean value indicating whether the number is negative. |
|
676 * @param source Value to be converted; must be >= 0. |
|
677 * @param maximumDigits The most digits which should be converted. |
|
678 * If maximumDigits is lower than the number of significant digits |
|
679 * in source, the representation will be rounded. Ignored if <= 0. |
|
680 */ |
|
681 final void set(boolean isNegative, BigInteger source, int maximumDigits) { |
|
682 this.isNegative = isNegative; |
|
683 String s = source.toString(); |
|
684 int len = s.length(); |
|
685 extendDigits(len); |
|
686 s.getChars(0, len, digits, 0); |
|
687 |
|
688 decimalAt = len; |
|
689 int right; |
|
690 for (right = len - 1; right >= 0 && digits[right] == '0'; --right) |
|
691 ; |
|
692 count = right + 1; |
|
693 |
|
694 if (maximumDigits > 0) { |
|
695 round(maximumDigits, false, true); |
|
696 } |
|
697 } |
|
698 |
|
699 /** |
|
700 * equality test between two digit lists. |
|
701 */ |
|
702 public boolean equals(Object obj) { |
|
703 if (this == obj) // quick check |
|
704 return true; |
|
705 if (!(obj instanceof DigitList)) // (1) same object? |
|
706 return false; |
|
707 DigitList other = (DigitList) obj; |
|
708 if (count != other.count || |
|
709 decimalAt != other.decimalAt) |
|
710 return false; |
|
711 for (int i = 0; i < count; i++) |
|
712 if (digits[i] != other.digits[i]) |
|
713 return false; |
|
714 return true; |
|
715 } |
|
716 |
|
717 /** |
|
718 * Generates the hash code for the digit list. |
|
719 */ |
|
720 public int hashCode() { |
|
721 int hashcode = decimalAt; |
|
722 |
|
723 for (int i = 0; i < count; i++) { |
|
724 hashcode = hashcode * 37 + digits[i]; |
|
725 } |
|
726 |
|
727 return hashcode; |
|
728 } |
|
729 |
|
730 /** |
|
731 * Creates a copy of this object. |
|
732 * @return a clone of this instance. |
|
733 */ |
|
734 public Object clone() { |
|
735 try { |
|
736 DigitList other = (DigitList) super.clone(); |
|
737 char[] newDigits = new char[digits.length]; |
|
738 System.arraycopy(digits, 0, newDigits, 0, digits.length); |
|
739 other.digits = newDigits; |
|
740 other.tempBuffer = null; |
|
741 return other; |
|
742 } catch (CloneNotSupportedException e) { |
|
743 throw new InternalError(e); |
|
744 } |
|
745 } |
|
746 |
|
747 /** |
|
748 * Returns true if this DigitList represents Long.MIN_VALUE; |
|
749 * false, otherwise. This is required so that getLong() works. |
|
750 */ |
|
751 private boolean isLongMIN_VALUE() { |
|
752 if (decimalAt != count || count != MAX_COUNT) { |
|
753 return false; |
|
754 } |
|
755 |
|
756 for (int i = 0; i < count; ++i) { |
|
757 if (digits[i] != LONG_MIN_REP[i]) return false; |
|
758 } |
|
759 |
|
760 return true; |
|
761 } |
|
762 |
|
763 private static final int parseInt(char[] str, int offset, int strLen) { |
|
764 char c; |
|
765 boolean positive = true; |
|
766 if ((c = str[offset]) == '-') { |
|
767 positive = false; |
|
768 offset++; |
|
769 } else if (c == '+') { |
|
770 offset++; |
|
771 } |
|
772 |
|
773 int value = 0; |
|
774 while (offset < strLen) { |
|
775 c = str[offset++]; |
|
776 if (c >= '0' && c <= '9') { |
|
777 value = value * 10 + (c - '0'); |
|
778 } else { |
|
779 break; |
|
780 } |
|
781 } |
|
782 return positive ? value : -value; |
|
783 } |
|
784 |
|
785 // The digit part of -9223372036854775808L |
|
786 private static final char[] LONG_MIN_REP = "9223372036854775808".toCharArray(); |
|
787 |
|
788 public String toString() { |
|
789 if (isZero()) { |
|
790 return "0"; |
|
791 } |
|
792 StringBuffer buf = getStringBuffer(); |
|
793 buf.append("0."); |
|
794 buf.append(digits, 0, count); |
|
795 buf.append("x10^"); |
|
796 buf.append(decimalAt); |
|
797 return buf.toString(); |
|
798 } |
|
799 |
|
800 private StringBuffer tempBuffer; |
|
801 |
|
802 private StringBuffer getStringBuffer() { |
|
803 if (tempBuffer == null) { |
|
804 tempBuffer = new StringBuffer(MAX_COUNT); |
|
805 } else { |
|
806 tempBuffer.setLength(0); |
|
807 } |
|
808 return tempBuffer; |
|
809 } |
|
810 |
|
811 private void extendDigits(int len) { |
|
812 if (len > digits.length) { |
|
813 digits = new char[len]; |
|
814 } |
|
815 } |
|
816 |
|
817 private final char[] getDataChars(int length) { |
|
818 if (data == null || data.length < length) { |
|
819 data = new char[length]; |
|
820 } |
|
821 return data; |
|
822 } |
|
823 } |