2 *******************************************************************************
3 * Copyright (C) 1996-2011, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
7 package com.ibm.icu.text;
9 import java.math.BigInteger;
12 * <code>DigitList</code> handles the transcoding between numeric values and
13 * strings of characters. It only represents non-negative numbers. The
14 * division of labor between <code>DigitList</code> and
15 * <code>DecimalFormat</code> is that <code>DigitList</code> handles the radix
16 * 10 representation issues and numeric conversion, including rounding;
17 * <code>DecimalFormat</code> handles the locale-specific issues such as
18 * positive and negative representation, digit grouping, decimal point,
19 * currency, and so on.
21 * <p>A <code>DigitList</code> is a representation of a finite numeric value.
22 * <code>DigitList</code> objects do not represent <code>NaN</code> or infinite
23 * values. A <code>DigitList</code> value can be converted to a
24 * <code>BigDecimal</code> without loss of precision. Conversion to other
25 * numeric formats may involve loss of precision, depending on the specific
28 * <p>The <code>DigitList</code> representation consists of a string of
29 * characters, which are the digits radix 10, from '0' to '9'. It also has a
30 * base 10 exponent associated with it. The value represented by a
31 * <code>DigitList</code> object can be computed by mulitplying the fraction
32 * <em>f</em>, where 0 <= <em>f</em> < 1, derived by placing all the digits of
33 * the list to the right of the decimal point, by 10^exponent.
35 * @see java.util.Locale
36 * @see java.text.Format
39 * @see java.text.ChoiceFormat
40 * @see java.text.MessageFormat
41 * @version 1.18 08/12/98
42 * @author Mark Davis, Alan Liu
44 final class DigitList {
46 * The maximum number of significant digits in an IEEE 754 double, that
47 * is, in a Java double. This must not be increased, or garbage digits
48 * will be generated, and should not be decreased, or accuracy will be lost.
50 public static final int MAX_LONG_DIGITS = 19; // == Long.toString(Long.MAX_VALUE).length()
51 public static final int DBL_DIG = 17;
54 * These data members are intentionally public and can be set directly.
56 * The value represented is given by placing the decimal point before
57 * digits[decimalAt]. If decimalAt is < 0, then leading zeros between
58 * the decimal point and the first nonzero digit are implied. If decimalAt
59 * is > count, then trailing zeros between the digits[count-1] and the
60 * decimal point are implied.
62 * Equivalently, the represented value is given by f * 10^decimalAt. Here
63 * f is a value 0.1 <= f < 1 arrived at by placing the digits in Digits to
64 * the right of the decimal.
66 * DigitList is normalized, so if it is non-zero, figits[0] is non-zero. We
67 * don't allow denormalized numbers because our exponent is effectively of
68 * unlimited magnitude. The count value contains the number of significant
69 * digits present in digits[].
71 * Zero is represented by any DigitList with count == 0 or with each digits[i]
72 * for all i <= count == '0'.
74 public int decimalAt = 0;
76 public byte[] digits = new byte[MAX_LONG_DIGITS];
78 private final void ensureCapacity(int digitCapacity, int digitsToCopy) {
79 if (digitCapacity > digits.length) {
80 byte[] newDigits = new byte[digitCapacity * 2];
81 System.arraycopy(digits, 0, newDigits, 0, digitsToCopy);
87 * Return true if the represented number is zero.
91 for (int i=0; i<count; ++i) if (digits[i] != '0') return false;
95 // Unused as of ICU 2.6 - alan
97 // * Clears out the digits.
98 // * Use before appending them.
99 // * Typically, you set a series of digits with append, then at the point
100 // * you hit the decimal point, you set myDigitList.decimalAt = myDigitList.count;
101 // * then go on appending digits.
103 // public void clear () {
109 * Appends digits to the list.
111 public void append (int digit) {
112 ensureCapacity(count+1, count);
113 digits[count++] = (byte) digit;
116 public byte getDigitValue(int i) {
117 return (byte) (digits[i] - '0');
121 * Utility routine to get the value of the digit list
122 * If (count == 0) this throws a NumberFormatException, which
123 * mimics Long.parseLong().
125 public final double getDouble() {
126 if (count == 0) return 0.0;
127 StringBuilder temp = new StringBuilder(count);
129 for (int i = 0; i < count; ++i) temp.append((char)(digits[i]));
131 temp.append(Integer.toString(decimalAt));
132 return Double.valueOf(temp.toString()).doubleValue();
133 // long value = Long.parseLong(temp.toString());
134 // return (value * Math.pow(10, decimalAt - count));
138 * Utility routine to get the value of the digit list.
139 * If (count == 0) this returns 0, unlike Long.parseLong().
141 public final long getLong() {
142 // for now, simple implementation; later, do proper IEEE native stuff
144 if (count == 0) return 0;
146 // We have to check for this, because this is the one NEGATIVE value
147 // we represent. If we tried to just pass the digits off to parseLong,
148 // we'd get a parse failure.
149 if (isLongMIN_VALUE()) return Long.MIN_VALUE;
151 StringBuilder temp = new StringBuilder(count);
152 for (int i = 0; i < decimalAt; ++i)
154 temp.append((i < count) ? (char)(digits[i]) : '0');
156 return Long.parseLong(temp.toString());
160 * Return a <code>BigInteger</code> representing the value stored in this
161 * <code>DigitList</code>. This method assumes that this object contains
162 * an integral value; if not, it will return an incorrect value.
164 * @param isPositive determines the sign of the returned result
165 * @return the value of this object as a <code>BigInteger</code>
167 public BigInteger getBigInteger(boolean isPositive) {
168 if (isZero()) return BigInteger.valueOf(0);
169 //Eclipse stated the following is "dead code"
171 StringBuilder stringRep = new StringBuilder(count);
173 stringRep.append('-');
175 for (int i=0; i<count; ++i) {
176 stringRep.append((char) digits[i]);
179 while (d-- > count) {
180 stringRep.append('0');
182 return new BigInteger(stringRep.toString());
184 int len = decimalAt > count ? decimalAt : count;
188 char[] text = new char[len];
192 for (int i = 0; i < count; ++i) {
193 text[i+1] = (char)digits[i];
197 for (int i = 0; i < count; ++i) {
198 text[i] = (char)digits[i];
202 for (int i = n; i < text.length; ++i) {
205 return new BigInteger(new String(text));
209 private String getStringRep(boolean isPositive) {
210 if (isZero()) return "0";
211 StringBuilder stringRep = new StringBuilder(count+1);
213 stringRep.append('-');
217 stringRep.append('.');
219 stringRep.append('0');
224 for (int i=0; i<count; ++i) {
226 stringRep.append('.');
228 stringRep.append((char) digits[i]);
230 while (d-- > count) {
231 stringRep.append('0');
233 return stringRep.toString();
237 * Return a <code>BigDecimal</code> representing the value stored in this
238 * <code>DigitList</code>.
240 * @param isPositive determines the sign of the returned result
241 * @return the value of this object as a <code>BigDecimal</code>
244 // The method is in a protected class and is not called by anything
245 public java.math.BigDecimal getBigDecimal(boolean isPositive) {
247 return java.math.BigDecimal.valueOf(0);
249 // if exponential notion is negative,
250 // we prefer to use BigDecimal constructor with scale,
251 // because it works better when extremely small value
252 // is used. See #5698.
253 long scale = (long)count - (long)decimalAt;
255 int numDigits = count;
256 if (scale > (long)Integer.MAX_VALUE) {
257 // try to reduce the scale
258 long numShift = scale - (long)Integer.MAX_VALUE;
259 if (numShift < count) {
260 numDigits -= numShift;
263 return new java.math.BigDecimal(0);
266 StringBuilder significantDigits = new StringBuilder(numDigits + 1);
268 significantDigits.append('-');
270 for (int i = 0; i < numDigits; i++) {
271 significantDigits.append((char)digits[i]);
273 BigInteger unscaledVal = new BigInteger(significantDigits.toString());
274 return new java.math.BigDecimal(unscaledVal, (int)scale);
276 // We should be able to use a negative scale value for a positive exponential
277 // value on JDK1.5. But it is not supported by older JDK. So, for now,
278 // we always use BigDecimal constructor which takes String.
279 return new java.math.BigDecimal(getStringRep(isPositive));
285 * Return an <code>ICU BigDecimal</code> representing the value stored in this
286 * <code>DigitList</code>.
288 * @param isPositive determines the sign of the returned result
289 * @return the value of this object as a <code>BigDecimal</code>
291 public com.ibm.icu.math.BigDecimal getBigDecimalICU(boolean isPositive) {
293 return com.ibm.icu.math.BigDecimal.valueOf(0);
295 // if exponential notion is negative,
296 // we prefer to use BigDecimal constructor with scale,
297 // because it works better when extremely small value
298 // is used. See #5698.
299 long scale = (long)count - (long)decimalAt;
301 int numDigits = count;
302 if (scale > (long)Integer.MAX_VALUE) {
303 // try to reduce the scale
304 long numShift = scale - (long)Integer.MAX_VALUE;
305 if (numShift < count) {
306 numDigits -= numShift;
309 return new com.ibm.icu.math.BigDecimal(0);
312 StringBuilder significantDigits = new StringBuilder(numDigits + 1);
314 significantDigits.append('-');
316 for (int i = 0; i < numDigits; i++) {
317 significantDigits.append((char)digits[i]);
319 BigInteger unscaledVal = new BigInteger(significantDigits.toString());
320 return new com.ibm.icu.math.BigDecimal(unscaledVal, (int)scale);
322 return new com.ibm.icu.math.BigDecimal(getStringRep(isPositive));
327 * Return whether or not this objects represented value is an integer.
329 * @return true if the represented value of this object is an integer
331 boolean isIntegral() {
332 // Trim trailing zeros. This does not change the represented value.
333 while (count > 0 && digits[count - 1] == (byte)'0') --count;
334 return count == 0 || decimalAt >= count;
337 // Unused as of ICU 2.6 - alan
339 // * Return true if the number represented by this object can fit into
342 // boolean fitsIntoLong(boolean isPositive)
344 // // Figure out if the result will fit in a long. We have to
345 // // first look for nonzero digits after the decimal point;
346 // // then check the size. If the digit count is 18 or less, then
347 // // the value can definitely be represented as a long. If it is 19
348 // // then it may be too large.
350 // // Trim trailing zeros. This does not change the represented value.
351 // while (count > 0 && digits[count - 1] == (byte)'0') --count;
354 // // Positive zero fits into a long, but negative zero can only
355 // // be represented as a double. - bug 4162852
356 // return isPositive;
359 // if (decimalAt < count || decimalAt > MAX_LONG_DIGITS) return false;
361 // if (decimalAt < MAX_LONG_DIGITS) return true;
363 // // At this point we have decimalAt == count, and count == MAX_LONG_DIGITS.
364 // // The number will overflow if it is larger than 9223372036854775807
365 // // or smaller than -9223372036854775808.
366 // for (int i=0; i<count; ++i)
368 // byte dig = digits[i], max = LONG_MIN_REP[i];
369 // if (dig > max) return false;
370 // if (dig < max) return true;
373 // // At this point the first count digits match. If decimalAt is less
374 // // than count, then the remaining digits are zero, and we return true.
375 // if (count < decimalAt) return true;
377 // // Now we have a representation of Long.MIN_VALUE, without the leading
378 // // negative sign. If this represents a positive value, then it does
379 // // not fit; otherwise it fits.
380 // return !isPositive;
383 // Unused as of ICU 2.6 - alan
385 // * Set the digit list to a representation of the given double value.
386 // * This method supports fixed-point notation.
387 // * @param source Value to be converted; must not be Inf, -Inf, Nan,
388 // * or a value <= 0.
389 // * @param maximumFractionDigits The most fractional digits which should
392 // public final void set(double source, int maximumFractionDigits)
394 // set(source, maximumFractionDigits, true);
398 * Set the digit list to a representation of the given double value.
399 * This method supports both fixed-point and exponential notation.
400 * @param source Value to be converted; must not be Inf, -Inf, Nan,
402 * @param maximumDigits The most fractional or total digits which should
404 * @param fixedPoint If true, then maximumDigits is the maximum
405 * fractional digits to be converted. If false, total digits.
407 final void set(double source, int maximumDigits, boolean fixedPoint)
409 if (source == 0) source = 0;
410 // Generate a representation of the form DDDDD, DDDDD.DDDDD, or
412 String rep = Double.toString(source);
414 set(rep, MAX_LONG_DIGITS);
417 // The negative of the exponent represents the number of leading
418 // zeros between the decimal and the first non-zero digit, for
419 // a value < 0.1 (e.g., for 0.00123, -decimalAt == 2). If this
420 // is more than the maximum fraction digits, then we have an underflow
421 // for the printed representation.
422 if (-decimalAt > maximumDigits) {
425 } else if (-decimalAt == maximumDigits) {
426 if (shouldRoundUp(0)) {
429 digits[0] = (byte)'1';
438 // Eliminate trailing zeros.
439 while (count > 1 && digits[count - 1] == '0')
442 // Eliminate digits beyond maximum digits to be displayed.
443 // Round up if appropriate.
444 round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits == 0 ? -1 : maximumDigits);
448 * Given a string representation of the form DDDDD, DDDDD.DDDDD,
449 * or DDDDDE+/-DDDDD, set this object's value to it. Ignore
452 private void set(String rep, int maxCount) {
456 // Number of zeros between decimal point and first non-zero digit after
457 // decimal point, for numbers < 1.
458 int leadingZerosAfterDecimal = 0;
459 boolean nonZeroDigitSeen = false;
460 // Skip over leading '-'
462 if (rep.charAt(i) == '-') {
465 for (; i < rep.length(); ++i) {
466 char c = rep.charAt(i);
469 } else if (c == 'e' || c == 'E') {
471 // Integer.parseInt doesn't handle leading '+' signs
472 if (rep.charAt(i) == '+') {
475 exponent = Integer.valueOf(rep.substring(i)).intValue();
477 } else if (count < maxCount) {
478 if (!nonZeroDigitSeen) {
479 nonZeroDigitSeen = (c != '0');
480 if (!nonZeroDigitSeen && decimalAt != -1) {
481 ++leadingZerosAfterDecimal;
485 if (nonZeroDigitSeen) {
486 ensureCapacity(count+1, count);
487 digits[count++] = (byte)c;
491 if (decimalAt == -1) {
494 decimalAt += exponent - leadingZerosAfterDecimal;
498 * Return true if truncating the representation to the given number
499 * of digits will result in an increment to the last digit. This
500 * method implements half-even rounding, the default rounding mode.
502 * @param maximumDigits the number of digits to keep, from 0 to
503 * <code>count-1</code>. If 0, then all digits are rounded away, and
504 * this method returns true if a one should be generated (e.g., formatting
506 * @return true if digit <code>maximumDigits-1</code> should be
509 private boolean shouldRoundUp(int maximumDigits) {
510 // variable not used boolean increment = false;
511 // Implement IEEE half-even rounding
513 format(0.0) gives "0.1" if preceded by parse("99.99") [Richard/GCL]
515 if (maximumDigits < count) {
516 if (digits[maximumDigits] > '5') {
518 } else if (digits[maximumDigits] == '5' ) {
519 for (int i=maximumDigits+1; i<count; ++i) {
520 if (digits[i] != '0') {
524 return maximumDigits > 0 && (digits[maximumDigits-1] % 2 != 0);
531 * Round the representation to the given number of digits.
532 * @param maximumDigits The maximum number of digits to be shown.
533 * Upon return, count will be less than or equal to maximumDigits.
534 * This now performs rounding when maximumDigits is 0, formerly it did not.
536 public final void round(int maximumDigits) {
537 // Eliminate digits beyond maximum digits to be displayed.
538 // Round up if appropriate.
539 // [bnf] rewritten to fix 4179818
540 if (maximumDigits >= 0 && maximumDigits < count) {
541 if (shouldRoundUp(maximumDigits)) {
542 // Rounding up involves incrementing digits from LSD to MSD.
543 // In most cases this is simple, but in a worst case situation
544 // (9999..99) we have to adjust the decimalAt value.
548 if (maximumDigits < 0)
550 // We have all 9's, so we increment to a single digit
551 // of one and adjust the exponent.
552 digits[0] = (byte) '1';
554 maximumDigits = 0; // Adjust the count
558 ++digits[maximumDigits];
559 if (digits[maximumDigits] <= '9') break;
560 // digits[maximumDigits] = '0'; // Unnecessary since we'll truncate this
562 ++maximumDigits; // Increment for use as count
564 count = maximumDigits;
566 // Bug 4217661 DecimalFormat formats 1.001 to "1.00" instead of "1"
567 // Eliminate trailing zeros. [Richard/GCL]
568 // [dlf] moved outside if block, see ticket #6408
569 while (count > 1 && digits[count-1] == '0') {
575 * Utility routine to set the value of the digit list from a long
577 public final void set(long source)
583 * Set the digit list to a representation of the given long value.
584 * @param source Value to be converted; must be >= 0 or ==
586 * @param maximumDigits The most digits which should be converted.
587 * If maximumDigits is lower than the number of significant digits
588 * in source, the representation will be rounded. Ignored if <= 0.
590 public final void set(long source, int maximumDigits)
592 // This method does not expect a negative number. However,
593 // "source" can be a Long.MIN_VALUE (-9223372036854775808),
594 // if the number being formatted is a Long.MIN_VALUE. In that
595 // case, it will be formatted as -Long.MIN_VALUE, a number
596 // which is outside the legal range of a long, but which can
597 // be represented by DigitList.
598 // [NEW] Faster implementation
600 if (source == Long.MIN_VALUE) {
601 decimalAt = count = MAX_LONG_DIGITS;
602 System.arraycopy(LONG_MIN_REP, 0, digits, 0, count);
608 int left = MAX_LONG_DIGITS;
611 digits[--left] = (byte) (((long) '0') + (source % 10));
614 decimalAt = MAX_LONG_DIGITS-left;
615 // Don't copy trailing zeros
616 // we are guaranteed that there is at least one non-zero digit,
617 // so we don't have to check lower bounds
618 for (right = MAX_LONG_DIGITS - 1; digits[right] == (byte) '0'; --right) {}
619 count = right - left + 1;
620 System.arraycopy(digits, left, digits, 0, count);
622 if (maximumDigits > 0) round(maximumDigits);
626 * Set the digit list to a representation of the given BigInteger value.
628 * @param source Value to be converted
629 * @param maximumDigits The most digits which should be converted.
630 * If maximumDigits is lower than the number of significant digits
631 * in source, the representation will be rounded. Ignored if <= 0.
633 public final void set(BigInteger source, int maximumDigits) {
634 String stringDigits = source.toString();
636 count = decimalAt = stringDigits.length();
638 // Don't copy trailing zeros
639 while (count > 1 && stringDigits.charAt(count - 1) == '0') --count;
642 if (stringDigits.charAt(0) == '-') {
648 ensureCapacity(count, 0);
649 for (int i = 0; i < count; ++i) {
650 digits[i] = (byte) stringDigits.charAt(i + offset);
653 if (maximumDigits > 0) round(maximumDigits);
657 * Internal method that sets this digit list to represent the
658 * given value. The value is given as a String of the format
659 * returned by BigDecimal.
660 * @param stringDigits value to be represented with the following
661 * syntax, expressed as a regular expression: -?\d*.?\d*
662 * Must not be an empty string.
663 * @param maximumDigits The most digits which should be converted.
664 * If maximumDigits is lower than the number of significant digits
665 * in source, the representation will be rounded. Ignored if <= 0.
666 * @param fixedPoint If true, then maximumDigits is the maximum
667 * fractional digits to be converted. If false, total digits.
669 private void setBigDecimalDigits(String stringDigits,
670 int maximumDigits, boolean fixedPoint) {
671 //| // Find the first non-zero digit, the decimal, and the last non-zero digit.
672 //| int first=-1, last=stringDigits.length()-1, decimal=-1;
673 //| for (int i=0; (first<0 || decimal<0) && i<=last; ++i) {
674 //| char c = stringDigits.charAt(i);
677 //| } else if (first < 0 && (c >= '1' && c <= '9')) {
687 //| // At this point we know there is at least one non-zero digit, so the
688 //| // following loop is safe.
690 //| char c = stringDigits.charAt(last);
691 //| if (c != '0' && c != '.') {
697 //| if (decimal < 0) {
698 //| decimal = stringDigits.length();
701 //| count = last - first;
702 //| if (decimal < first || decimal > last) {
705 //| decimalAt = decimal - first;
706 //| if (decimalAt < 0) {
710 //| ensureCapacity(count, 0);
711 //| for (int i = 0; i < count; ++i) {
712 //| digits[i] = (byte) stringDigits.charAt(first++);
713 //| if (first == decimal) {
718 // The maxDigits here could also be Integer.MAX_VALUE
719 set(stringDigits, stringDigits.length());
721 // Eliminate digits beyond maximum digits to be displayed.
722 // Round up if appropriate.
723 // {dlf} Some callers depend on passing '0' to round to mean 'don't round', but
724 // rather than pass that information explicitly, we rely on some magic with maximumDigits
725 // and decimalAt. Unfortunately, this is no good, because there are cases where maximumDigits
726 // is zero and we do want to round, e.g. BigDecimal values -1 < x < 1. So since round
727 // changed to perform rounding when the argument is 0, we now force the argument
728 // to -1 in the situations where it matters.
729 round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits == 0 ? -1 : maximumDigits);
733 * Set the digit list to a representation of the given BigDecimal value.
735 * @param source Value to be converted
736 * @param maximumDigits The most digits which should be converted.
737 * If maximumDigits is lower than the number of significant digits
738 * in source, the representation will be rounded. Ignored if <= 0.
739 * @param fixedPoint If true, then maximumDigits is the maximum
740 * fractional digits to be converted. If false, total digits.
742 public final void set(java.math.BigDecimal source,
743 int maximumDigits, boolean fixedPoint) {
744 setBigDecimalDigits(source.toString(), maximumDigits, fixedPoint);
748 * Set the digit list to a representation of the given BigDecimal value.
750 * @param source Value to be converted
751 * @param maximumDigits The most digits which should be converted.
752 * If maximumDigits is lower than the number of significant digits
753 * in source, the representation will be rounded. Ignored if <= 0.
754 * @param fixedPoint If true, then maximumDigits is the maximum
755 * fractional digits to be converted. If false, total digits.
757 public final void set(com.ibm.icu.math.BigDecimal source,
758 int maximumDigits, boolean fixedPoint) {
759 setBigDecimalDigits(source.toString(), maximumDigits, fixedPoint);
763 * Returns true if this DigitList represents Long.MIN_VALUE;
764 * false, otherwise. This is required so that getLong() works.
766 private boolean isLongMIN_VALUE()
768 if (decimalAt != count || count != MAX_LONG_DIGITS)
771 for (int i = 0; i < count; ++i)
773 if (digits[i] != LONG_MIN_REP[i]) return false;
779 private static byte[] LONG_MIN_REP;
783 // Store the representation of LONG_MIN without the leading '-'
784 String s = Long.toString(Long.MIN_VALUE);
785 LONG_MIN_REP = new byte[MAX_LONG_DIGITS];
786 for (int i=0; i < MAX_LONG_DIGITS; ++i)
788 LONG_MIN_REP[i] = (byte)s.charAt(i + 1);
792 // Unused -- Alan 2003-05
794 // * Return the floor of the log base 10 of a given double.
795 // * This method compensates for inaccuracies which arise naturally when
796 // * computing logs, and always give the correct value. The parameter
797 // * must be positive and finite.
799 // private static final int log10(double d)
801 // // The reason this routine is needed is that simply taking the
802 // // log and dividing by log10 yields a result which may be off
803 // // by 1 due to rounding errors. For example, the naive log10
804 // // of 1.0e300 taken this way is 299, rather than 300.
805 // double log10 = Math.log(d) / LOG10;
806 // int ilog10 = (int)Math.floor(log10);
807 // // Positive logs could be too small, e.g. 0.99 instead of 1.0
808 // if (log10 > 0 && d >= Math.pow(10, ilog10 + 1))
812 // // Negative logs could be too big, e.g. -0.99 instead of -1.0
813 // else if (log10 < 0 && d < Math.pow(10, ilog10))
820 // private static final double LOG10 = Math.log(10.0);
822 // (The following boilerplate methods are currently not called,
823 // and cannot be called by tests since this class is
824 // package-private. The methods may be useful in the future, so
825 // we do not delete them. 2003-06-11 ICU 2.6 Alan)
828 * equality test between two digit lists.
830 public boolean equals(Object obj) {
831 if (this == obj) // quick check
833 if (!(obj instanceof DigitList)) // (1) same object?
835 DigitList other = (DigitList) obj;
836 if (count != other.count ||
837 decimalAt != other.decimalAt)
839 for (int i = 0; i < count; i++)
840 if (digits[i] != other.digits[i])
846 * Generates the hash code for the digit list.
848 public int hashCode() {
849 int hashcode = decimalAt;
851 for (int i = 0; i < count; i++)
852 hashcode = hashcode * 37 + digits[i];
857 public String toString()
859 if (isZero()) return "0";
860 StringBuilder buf = new StringBuilder("0.");
861 for (int i=0; i<count; ++i) buf.append((char)digits[i]);
863 buf.append(decimalAt);
864 return buf.toString();