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 sun.misc.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 } 538 else { 539 // Digit at rounding position is the last one ! 540 if (valueExactAsDecimal) { 541 // Exact binary representation. On the tie. 542 // Apply rounding given by roundingMode. 543 // I.e. we round-up only if roundingMode is HALF_UP. 544 return roundingMode == RoundingMode.HALF_UP; 545 } 546 else { 547 // Not an exact binary representation. 548 if (alreadyRounded) { 549 // Digit sequence rounded-up. Was below tie. 550 // Don't round-up twice ! 551 return false; 552 } 553 else { 554 // Digit sequence truncated. Was above tie. 555 // must round-up ! 556 return true; 557 } 558 } 559 } 560 } 561 // Digit at rounding position is < '5' ==> no round-up. 562 // Just let do the default, which is no round-up (thus break). 563 break; 564 case HALF_EVEN: 565 // Implement IEEE half-even rounding 566 if (digits[maximumDigits] > '5') { 567 return true; 568 } else if (digits[maximumDigits] == '5' ) { 569 if (maximumDigits == (count - 1)) { 570 // the rounding position is exactly the last index : 571 if (alreadyRounded) 572 // If FloatingDecimal rounded up (value was below tie), 573 // then we should not round up again. 574 return false; 575 576 if (!valueExactAsDecimal) 577 // Otherwise if the digits don't represent exact value, 578 // value was above tie and FloatingDecimal truncated 579 // digits to tie. We must round up. 580 return true; 581 else { 582 // This is an exact tie value, and FloatingDecimal 583 // provided all of the exact digits. We thus apply 584 // HALF_EVEN rounding rule. 585 return ((maximumDigits > 0) && 586 (digits[maximumDigits-1] % 2 != 0)); 587 } 588 } else { 589 // Rounds up if it gives a non null digit after '5' 590 for (int i=maximumDigits+1; i<count; ++i) { 591 if (digits[i] != '0') 592 return true; 593 } 594 } 595 } 596 break; 597 case UNNECESSARY: 598 for (int i=maximumDigits; i<count; ++i) { 599 if (digits[i] != '0') { 600 throw new ArithmeticException( 601 "Rounding needed with the rounding mode being set to RoundingMode.UNNECESSARY"); 602 } 603 } 604 break; 605 default: 606 assert false; 607 } 608 } 609 return false; 610 } 611 612 /** 613 * Utility routine to set the value of the digit list from a long 614 */ 615 final void set(boolean isNegative, long source) { 616 set(isNegative, source, 0); 617 } 618 619 /** 620 * Set the digit list to a representation of the given long value. 621 * @param isNegative Boolean value indicating whether the number is negative. 622 * @param source Value to be converted; must be >= 0 or == 623 * Long.MIN_VALUE. 624 * @param maximumDigits The most digits which should be converted. 625 * If maximumDigits is lower than the number of significant digits 626 * in source, the representation will be rounded. Ignored if <= 0. 627 */ 628 final void set(boolean isNegative, long source, int maximumDigits) { 629 this.isNegative = isNegative; 630 631 // This method does not expect a negative number. However, 632 // "source" can be a Long.MIN_VALUE (-9223372036854775808), 633 // if the number being formatted is a Long.MIN_VALUE. In that 634 // case, it will be formatted as -Long.MIN_VALUE, a number 635 // which is outside the legal range of a long, but which can 636 // be represented by DigitList. 637 if (source <= 0) { 638 if (source == Long.MIN_VALUE) { 639 decimalAt = count = MAX_COUNT; 640 System.arraycopy(LONG_MIN_REP, 0, digits, 0, count); 641 } else { 642 decimalAt = count = 0; // Values <= 0 format as zero 643 } 644 } else { 645 // Rewritten to improve performance. I used to call 646 // Long.toString(), which was about 4x slower than this code. 647 int left = MAX_COUNT; 648 int right; 649 while (source > 0) { 650 digits[--left] = (char)('0' + (source % 10)); 651 source /= 10; 652 } 653 decimalAt = MAX_COUNT - left; 654 // Don't copy trailing zeros. We are guaranteed that there is at 655 // least one non-zero digit, so we don't have to check lower bounds. 656 for (right = MAX_COUNT - 1; digits[right] == '0'; --right) 657 ; 658 count = right - left + 1; 659 System.arraycopy(digits, left, digits, 0, count); 660 } 661 if (maximumDigits > 0) round(maximumDigits, false, true); 662 } 663 664 /** 665 * Set the digit list to a representation of the given BigDecimal value. 666 * This method supports both fixed-point and exponential notation. 667 * @param isNegative Boolean value indicating whether the number is negative. 668 * @param source Value to be converted; must not be a value <= 0. 669 * @param maximumDigits The most fractional or total digits which should 670 * be converted. 671 * @param fixedPoint If true, then maximumDigits is the maximum 672 * fractional digits to be converted. If false, total digits. 673 */ 674 final void set(boolean isNegative, BigDecimal source, int maximumDigits, boolean fixedPoint) { 675 String s = source.toString(); 676 extendDigits(s.length()); 677 678 set(isNegative, s, 679 false, true, 680 maximumDigits, fixedPoint); 681 } 682 683 /** 684 * Set the digit list to a representation of the given BigInteger value. 685 * @param isNegative Boolean value indicating whether the number is negative. 686 * @param source Value to be converted; must be >= 0. 687 * @param maximumDigits The most digits which should be converted. 688 * If maximumDigits is lower than the number of significant digits 689 * in source, the representation will be rounded. Ignored if <= 0. 690 */ 691 final void set(boolean isNegative, BigInteger source, int maximumDigits) { 692 this.isNegative = isNegative; 693 String s = source.toString(); 694 int len = s.length(); 695 extendDigits(len); 696 s.getChars(0, len, digits, 0); 697 698 decimalAt = len; 699 int right; 700 for (right = len - 1; right >= 0 && digits[right] == '0'; --right) 701 ; 702 count = right + 1; 703 704 if (maximumDigits > 0) { 705 round(maximumDigits, false, true); 706 } 707 } 708 709 /** 710 * equality test between two digit lists. 711 */ 712 public boolean equals(Object obj) { 713 if (this == obj) // quick check 714 return true; 715 if (!(obj instanceof DigitList)) // (1) same object? 716 return false; 717 DigitList other = (DigitList) obj; 718 if (count != other.count || 719 decimalAt != other.decimalAt) 720 return false; 721 for (int i = 0; i < count; i++) 722 if (digits[i] != other.digits[i]) 723 return false; 724 return true; 725 } 726 727 /** 728 * Generates the hash code for the digit list. 729 */ 730 public int hashCode() { 731 int hashcode = decimalAt; 732 733 for (int i = 0; i < count; i++) { 734 hashcode = hashcode * 37 + digits[i]; 735 } 736 737 return hashcode; 738 } 739 740 /** 741 * Creates a copy of this object. 742 * @return a clone of this instance. 743 */ 744 public Object clone() { 745 try { 746 DigitList other = (DigitList) super.clone(); 747 char[] newDigits = new char[digits.length]; 748 System.arraycopy(digits, 0, newDigits, 0, digits.length); 749 other.digits = newDigits; 750 other.tempBuffer = null; 751 return other; 752 } catch (CloneNotSupportedException e) { 753 throw new InternalError(e); 754 } 755 } 756 757 /** 758 * Returns true if this DigitList represents Long.MIN_VALUE; 759 * false, otherwise. This is required so that getLong() works. 760 */ 761 private boolean isLongMIN_VALUE() { 762 if (decimalAt != count || count != MAX_COUNT) { 763 return false; 764 } 765 766 for (int i = 0; i < count; ++i) { 767 if (digits[i] != LONG_MIN_REP[i]) return false; 768 } 769 770 return true; 771 } 772 773 private static final int parseInt(char[] str, int offset, int strLen) { 774 char c; 775 boolean positive = true; 776 if ((c = str[offset]) == '-') { 777 positive = false; 778 offset++; 779 } else if (c == '+') { 780 offset++; 781 } 782 783 int value = 0; 784 while (offset < strLen) { 785 c = str[offset++]; 786 if (c >= '0' && c <= '9') { 787 value = value * 10 + (c - '0'); 788 } else { 789 break; 790 } 791 } 792 return positive ? value : -value; 793 } 794 795 // The digit part of -9223372036854775808L 796 private static final char[] LONG_MIN_REP = "9223372036854775808".toCharArray(); 797 798 public String toString() { 799 if (isZero()) { 800 return "0"; 801 } 802 StringBuffer buf = getStringBuffer(); 803 buf.append("0."); 804 buf.append(digits, 0, count); 805 buf.append("x10^"); 806 buf.append(decimalAt); 807 return buf.toString(); 808 } 809 810 private StringBuffer tempBuffer; 811 812 private StringBuffer getStringBuffer() { 813 if (tempBuffer == null) { 814 tempBuffer = new StringBuffer(MAX_COUNT); 815 } else { 816 tempBuffer.setLength(0); 817 } 818 return tempBuffer; 819 } 820 821 private void extendDigits(int len) { 822 if (len > digits.length) { 823 digits = new char[len]; 824 } 825 } 826 827 private final char[] getDataChars(int length) { 828 if (data == null || data.length < length) { 829 data = new char[length]; 830 } 831 return data; 832 } 833 }