2 *******************************************************************************
\r
3 * Copyright (C) 1996-2010, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
7 package com.ibm.icu.text;
\r
9 import java.math.BigInteger;
\r
12 * <code>DigitList</code> handles the transcoding between numeric values and
\r
13 * strings of characters. It only represents non-negative numbers. The
\r
14 * division of labor between <code>DigitList</code> and
\r
15 * <code>DecimalFormat</code> is that <code>DigitList</code> handles the radix
\r
16 * 10 representation issues and numeric conversion, including rounding;
\r
17 * <code>DecimalFormat</code> handles the locale-specific issues such as
\r
18 * positive and negative representation, digit grouping, decimal point,
\r
19 * currency, and so on.
\r
21 * <p>A <code>DigitList</code> is a representation of a finite numeric value.
\r
22 * <code>DigitList</code> objects do not represent <code>NaN</code> or infinite
\r
23 * values. A <code>DigitList</code> value can be converted to a
\r
24 * <code>BigDecimal</code> without loss of precision. Conversion to other
\r
25 * numeric formats may involve loss of precision, depending on the specific
\r
28 * <p>The <code>DigitList</code> representation consists of a string of
\r
29 * characters, which are the digits radix 10, from '0' to '9'. It also has a
\r
30 * base 10 exponent associated with it. The value represented by a
\r
31 * <code>DigitList</code> object can be computed by mulitplying the fraction
\r
32 * <em>f</em>, where 0 <= <em>f</em> < 1, derived by placing all the digits of
\r
33 * the list to the right of the decimal point, by 10^exponent.
\r
35 * @see java.util.Locale
\r
36 * @see java.text.Format
\r
38 * @see DecimalFormat
\r
39 * @see java.text.ChoiceFormat
\r
40 * @see java.text.MessageFormat
\r
41 * @version 1.18 08/12/98
\r
42 * @author Mark Davis, Alan Liu
\r
44 final class DigitList {
\r
46 * The maximum number of significant digits in an IEEE 754 double, that
\r
47 * is, in a Java double. This must not be increased, or garbage digits
\r
48 * will be generated, and should not be decreased, or accuracy will be lost.
\r
50 public static final int MAX_LONG_DIGITS = 19; // == Long.toString(Long.MAX_VALUE).length()
\r
51 public static final int DBL_DIG = 17;
\r
54 * These data members are intentionally public and can be set directly.
\r
56 * The value represented is given by placing the decimal point before
\r
57 * digits[decimalAt]. If decimalAt is < 0, then leading zeros between
\r
58 * the decimal point and the first nonzero digit are implied. If decimalAt
\r
59 * is > count, then trailing zeros between the digits[count-1] and the
\r
60 * decimal point are implied.
\r
62 * Equivalently, the represented value is given by f * 10^decimalAt. Here
\r
63 * f is a value 0.1 <= f < 1 arrived at by placing the digits in Digits to
\r
64 * the right of the decimal.
\r
66 * DigitList is normalized, so if it is non-zero, figits[0] is non-zero. We
\r
67 * don't allow denormalized numbers because our exponent is effectively of
\r
68 * unlimited magnitude. The count value contains the number of significant
\r
69 * digits present in digits[].
\r
71 * Zero is represented by any DigitList with count == 0 or with each digits[i]
\r
72 * for all i <= count == '0'.
\r
74 public int decimalAt = 0;
\r
75 public int count = 0;
\r
76 public byte[] digits = new byte[MAX_LONG_DIGITS];
\r
78 private final void ensureCapacity(int digitCapacity, int digitsToCopy) {
\r
79 if (digitCapacity > digits.length) {
\r
80 byte[] newDigits = new byte[digitCapacity * 2];
\r
81 System.arraycopy(digits, 0, newDigits, 0, digitsToCopy);
\r
87 * Return true if the represented number is zero.
\r
91 for (int i=0; i<count; ++i) if (digits[i] != '0') return false;
\r
95 // Unused as of ICU 2.6 - alan
\r
97 // * Clears out the digits.
\r
98 // * Use before appending them.
\r
99 // * Typically, you set a series of digits with append, then at the point
\r
100 // * you hit the decimal point, you set myDigitList.decimalAt = myDigitList.count;
\r
101 // * then go on appending digits.
\r
103 // public void clear () {
\r
109 * Appends digits to the list.
\r
111 public void append (int digit) {
\r
112 ensureCapacity(count+1, count);
\r
113 digits[count++] = (byte) digit;
\r
116 * Utility routine to get the value of the digit list
\r
117 * If (count == 0) this throws a NumberFormatException, which
\r
118 * mimics Long.parseLong().
\r
120 public final double getDouble() {
\r
121 if (count == 0) return 0.0;
\r
122 StringBuilder temp = new StringBuilder(count);
\r
124 for (int i = 0; i < count; ++i) temp.append((char)(digits[i]));
\r
126 temp.append(Integer.toString(decimalAt));
\r
127 return Double.valueOf(temp.toString()).doubleValue();
\r
128 // long value = Long.parseLong(temp.toString());
\r
129 // return (value * Math.pow(10, decimalAt - count));
\r
133 * Utility routine to get the value of the digit list.
\r
134 * If (count == 0) this returns 0, unlike Long.parseLong().
\r
136 public final long getLong() {
\r
137 // for now, simple implementation; later, do proper IEEE native stuff
\r
139 if (count == 0) return 0;
\r
141 // We have to check for this, because this is the one NEGATIVE value
\r
142 // we represent. If we tried to just pass the digits off to parseLong,
\r
143 // we'd get a parse failure.
\r
144 if (isLongMIN_VALUE()) return Long.MIN_VALUE;
\r
146 StringBuilder temp = new StringBuilder(count);
\r
147 for (int i = 0; i < decimalAt; ++i)
\r
149 temp.append((i < count) ? (char)(digits[i]) : '0');
\r
151 return Long.parseLong(temp.toString());
\r
155 * Return a <code>BigInteger</code> representing the value stored in this
\r
156 * <code>DigitList</code>. This method assumes that this object contains
\r
157 * an integral value; if not, it will return an incorrect value.
\r
159 * @param isPositive determines the sign of the returned result
\r
160 * @return the value of this object as a <code>BigInteger</code>
\r
162 public BigInteger getBigInteger(boolean isPositive) {
\r
163 if (isZero()) return BigInteger.valueOf(0);
\r
164 //Eclipse stated the following is "dead code"
\r
166 StringBuilder stringRep = new StringBuilder(count);
\r
168 stringRep.append('-');
\r
170 for (int i=0; i<count; ++i) {
\r
171 stringRep.append((char) digits[i]);
\r
174 while (d-- > count) {
\r
175 stringRep.append('0');
\r
177 return new BigInteger(stringRep.toString());
\r
179 int len = decimalAt > count ? decimalAt : count;
\r
183 char[] text = new char[len];
\r
187 for (int i = 0; i < count; ++i) {
\r
188 text[i+1] = (char)digits[i];
\r
192 for (int i = 0; i < count; ++i) {
\r
193 text[i] = (char)digits[i];
\r
197 for (int i = n; i < text.length; ++i) {
\r
200 return new BigInteger(new String(text));
\r
204 private String getStringRep(boolean isPositive) {
\r
205 if (isZero()) return "0";
\r
206 StringBuilder stringRep = new StringBuilder(count+1);
\r
208 stringRep.append('-');
\r
212 stringRep.append('.');
\r
214 stringRep.append('0');
\r
219 for (int i=0; i<count; ++i) {
\r
221 stringRep.append('.');
\r
223 stringRep.append((char) digits[i]);
\r
225 while (d-- > count) {
\r
226 stringRep.append('0');
\r
228 return stringRep.toString();
\r
232 * Return a <code>BigDecimal</code> representing the value stored in this
\r
233 * <code>DigitList</code>.
\r
235 * @param isPositive determines the sign of the returned result
\r
236 * @return the value of this object as a <code>BigDecimal</code>
\r
239 // The method is in a protected class and is not called by anything
\r
240 public java.math.BigDecimal getBigDecimal(boolean isPositive) {
\r
242 return java.math.BigDecimal.valueOf(0);
\r
244 // if exponential notion is negative,
\r
245 // we prefer to use BigDecimal constructor with scale,
\r
246 // because it works better when extremely small value
\r
247 // is used. See #5698.
\r
248 long scale = (long)count - (long)decimalAt;
\r
250 int numDigits = count;
\r
251 if (scale > (long)Integer.MAX_VALUE) {
\r
252 // try to reduce the scale
\r
253 long numShift = scale - (long)Integer.MAX_VALUE;
\r
254 if (numShift < count) {
\r
255 numDigits -= numShift;
\r
258 return new java.math.BigDecimal(0);
\r
261 StringBuilder significantDigits = new StringBuilder(numDigits + 1);
\r
263 significantDigits.append('-');
\r
265 for (int i = 0; i < numDigits; i++) {
\r
266 significantDigits.append((char)digits[i]);
\r
268 BigInteger unscaledVal = new BigInteger(significantDigits.toString());
\r
269 return new java.math.BigDecimal(unscaledVal, (int)scale);
\r
271 // We should be able to use a negative scale value for a positive exponential
\r
272 // value on JDK1.5. But it is not supported by older JDK. So, for now,
\r
273 // we always use BigDecimal constructor which takes String.
\r
274 return new java.math.BigDecimal(getStringRep(isPositive));
\r
280 * Return an <code>ICU BigDecimal</code> representing the value stored in this
\r
281 * <code>DigitList</code>.
\r
283 * @param isPositive determines the sign of the returned result
\r
284 * @return the value of this object as a <code>BigDecimal</code>
\r
286 public com.ibm.icu.math.BigDecimal getBigDecimalICU(boolean isPositive) {
\r
288 return com.ibm.icu.math.BigDecimal.valueOf(0);
\r
290 // if exponential notion is negative,
\r
291 // we prefer to use BigDecimal constructor with scale,
\r
292 // because it works better when extremely small value
\r
293 // is used. See #5698.
\r
294 long scale = (long)count - (long)decimalAt;
\r
296 int numDigits = count;
\r
297 if (scale > (long)Integer.MAX_VALUE) {
\r
298 // try to reduce the scale
\r
299 long numShift = scale - (long)Integer.MAX_VALUE;
\r
300 if (numShift < count) {
\r
301 numDigits -= numShift;
\r
304 return new com.ibm.icu.math.BigDecimal(0);
\r
307 StringBuilder significantDigits = new StringBuilder(numDigits + 1);
\r
309 significantDigits.append('-');
\r
311 for (int i = 0; i < numDigits; i++) {
\r
312 significantDigits.append((char)digits[i]);
\r
314 BigInteger unscaledVal = new BigInteger(significantDigits.toString());
\r
315 return new com.ibm.icu.math.BigDecimal(unscaledVal, (int)scale);
\r
317 return new com.ibm.icu.math.BigDecimal(getStringRep(isPositive));
\r
322 * Return whether or not this objects represented value is an integer.
\r
324 * @return true if the represented value of this object is an integer
\r
326 boolean isIntegral() {
\r
327 // Trim trailing zeros. This does not change the represented value.
\r
328 while (count > 0 && digits[count - 1] == (byte)'0') --count;
\r
329 return count == 0 || decimalAt >= count;
\r
332 // Unused as of ICU 2.6 - alan
\r
334 // * Return true if the number represented by this object can fit into
\r
337 // boolean fitsIntoLong(boolean isPositive)
\r
339 // // Figure out if the result will fit in a long. We have to
\r
340 // // first look for nonzero digits after the decimal point;
\r
341 // // then check the size. If the digit count is 18 or less, then
\r
342 // // the value can definitely be represented as a long. If it is 19
\r
343 // // then it may be too large.
\r
345 // // Trim trailing zeros. This does not change the represented value.
\r
346 // while (count > 0 && digits[count - 1] == (byte)'0') --count;
\r
348 // if (count == 0) {
\r
349 // // Positive zero fits into a long, but negative zero can only
\r
350 // // be represented as a double. - bug 4162852
\r
351 // return isPositive;
\r
354 // if (decimalAt < count || decimalAt > MAX_LONG_DIGITS) return false;
\r
356 // if (decimalAt < MAX_LONG_DIGITS) return true;
\r
358 // // At this point we have decimalAt == count, and count == MAX_LONG_DIGITS.
\r
359 // // The number will overflow if it is larger than 9223372036854775807
\r
360 // // or smaller than -9223372036854775808.
\r
361 // for (int i=0; i<count; ++i)
\r
363 // byte dig = digits[i], max = LONG_MIN_REP[i];
\r
364 // if (dig > max) return false;
\r
365 // if (dig < max) return true;
\r
368 // // At this point the first count digits match. If decimalAt is less
\r
369 // // than count, then the remaining digits are zero, and we return true.
\r
370 // if (count < decimalAt) return true;
\r
372 // // Now we have a representation of Long.MIN_VALUE, without the leading
\r
373 // // negative sign. If this represents a positive value, then it does
\r
374 // // not fit; otherwise it fits.
\r
375 // return !isPositive;
\r
378 // Unused as of ICU 2.6 - alan
\r
380 // * Set the digit list to a representation of the given double value.
\r
381 // * This method supports fixed-point notation.
\r
382 // * @param source Value to be converted; must not be Inf, -Inf, Nan,
\r
383 // * or a value <= 0.
\r
384 // * @param maximumFractionDigits The most fractional digits which should
\r
387 // public final void set(double source, int maximumFractionDigits)
\r
389 // set(source, maximumFractionDigits, true);
\r
393 * Set the digit list to a representation of the given double value.
\r
394 * This method supports both fixed-point and exponential notation.
\r
395 * @param source Value to be converted; must not be Inf, -Inf, Nan,
\r
397 * @param maximumDigits The most fractional or total digits which should
\r
399 * @param fixedPoint If true, then maximumDigits is the maximum
\r
400 * fractional digits to be converted. If false, total digits.
\r
402 final void set(double source, int maximumDigits, boolean fixedPoint)
\r
404 if (source == 0) source = 0;
\r
405 // Generate a representation of the form DDDDD, DDDDD.DDDDD, or
\r
407 String rep = Double.toString(source);
\r
409 set(rep, MAX_LONG_DIGITS);
\r
412 // The negative of the exponent represents the number of leading
\r
413 // zeros between the decimal and the first non-zero digit, for
\r
414 // a value < 0.1 (e.g., for 0.00123, -decimalAt == 2). If this
\r
415 // is more than the maximum fraction digits, then we have an underflow
\r
416 // for the printed representation.
\r
417 if (-decimalAt > maximumDigits) {
\r
420 } else if (-decimalAt == maximumDigits) {
\r
421 if (shouldRoundUp(0)) {
\r
424 digits[0] = (byte)'1';
\r
430 // else fall through
\r
433 // Eliminate trailing zeros.
\r
434 while (count > 1 && digits[count - 1] == '0')
\r
437 // Eliminate digits beyond maximum digits to be displayed.
\r
438 // Round up if appropriate.
\r
439 round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits == 0 ? -1 : maximumDigits);
\r
443 * Given a string representation of the form DDDDD, DDDDD.DDDDD,
\r
444 * or DDDDDE+/-DDDDD, set this object's value to it. Ignore
\r
447 private void set(String rep, int maxCount) {
\r
451 // Number of zeros between decimal point and first non-zero digit after
\r
452 // decimal point, for numbers < 1.
\r
453 int leadingZerosAfterDecimal = 0;
\r
454 boolean nonZeroDigitSeen = false;
\r
455 // Skip over leading '-'
\r
457 if (rep.charAt(i) == '-') {
\r
460 for (; i < rep.length(); ++i) {
\r
461 char c = rep.charAt(i);
\r
464 } else if (c == 'e' || c == 'E') {
\r
466 // Integer.parseInt doesn't handle leading '+' signs
\r
467 if (rep.charAt(i) == '+') {
\r
470 exponent = Integer.valueOf(rep.substring(i)).intValue();
\r
472 } else if (count < maxCount) {
\r
473 if (!nonZeroDigitSeen) {
\r
474 nonZeroDigitSeen = (c != '0');
\r
475 if (!nonZeroDigitSeen && decimalAt != -1) {
\r
476 ++leadingZerosAfterDecimal;
\r
480 if (nonZeroDigitSeen) {
\r
481 ensureCapacity(count+1, count);
\r
482 digits[count++] = (byte)c;
\r
486 if (decimalAt == -1) {
\r
489 decimalAt += exponent - leadingZerosAfterDecimal;
\r
493 * Return true if truncating the representation to the given number
\r
494 * of digits will result in an increment to the last digit. This
\r
495 * method implements half-even rounding, the default rounding mode.
\r
497 * @param maximumDigits the number of digits to keep, from 0 to
\r
498 * <code>count-1</code>. If 0, then all digits are rounded away, and
\r
499 * this method returns true if a one should be generated (e.g., formatting
\r
500 * 0.09 with "#.#").
\r
501 * @return true if digit <code>maximumDigits-1</code> should be
\r
504 private boolean shouldRoundUp(int maximumDigits) {
\r
505 // variable not used boolean increment = false;
\r
506 // Implement IEEE half-even rounding
\r
508 format(0.0) gives "0.1" if preceded by parse("99.99") [Richard/GCL]
\r
510 if (maximumDigits < count) {
\r
511 if (digits[maximumDigits] > '5') {
\r
513 } else if (digits[maximumDigits] == '5' ) {
\r
514 for (int i=maximumDigits+1; i<count; ++i) {
\r
515 if (digits[i] != '0') {
\r
519 return maximumDigits > 0 && (digits[maximumDigits-1] % 2 != 0);
\r
526 * Round the representation to the given number of digits.
\r
527 * @param maximumDigits The maximum number of digits to be shown.
\r
528 * Upon return, count will be less than or equal to maximumDigits.
\r
529 * This now performs rounding when maximumDigits is 0, formerly it did not.
\r
531 public final void round(int maximumDigits) {
\r
532 // Eliminate digits beyond maximum digits to be displayed.
\r
533 // Round up if appropriate.
\r
534 // [bnf] rewritten to fix 4179818
\r
535 if (maximumDigits >= 0 && maximumDigits < count) {
\r
536 if (shouldRoundUp(maximumDigits)) {
\r
537 // Rounding up involves incrementing digits from LSD to MSD.
\r
538 // In most cases this is simple, but in a worst case situation
\r
539 // (9999..99) we have to adjust the decimalAt value.
\r
543 if (maximumDigits < 0)
\r
545 // We have all 9's, so we increment to a single digit
\r
546 // of one and adjust the exponent.
\r
547 digits[0] = (byte) '1';
\r
549 maximumDigits = 0; // Adjust the count
\r
553 ++digits[maximumDigits];
\r
554 if (digits[maximumDigits] <= '9') break;
\r
555 // digits[maximumDigits] = '0'; // Unnecessary since we'll truncate this
\r
557 ++maximumDigits; // Increment for use as count
\r
559 count = maximumDigits;
\r
560 /*Bug 4217661 DecimalFormat formats 1.001 to "1.00" instead of "1"
\r
561 Eliminate trailing zeros. [Richard/GCL]
\r
563 while (count > 1 && digits[count-1] == '0') {
\r
570 * Utility routine to set the value of the digit list from a long
\r
572 public final void set(long source)
\r
578 * Set the digit list to a representation of the given long value.
\r
579 * @param source Value to be converted; must be >= 0 or ==
\r
581 * @param maximumDigits The most digits which should be converted.
\r
582 * If maximumDigits is lower than the number of significant digits
\r
583 * in source, the representation will be rounded. Ignored if <= 0.
\r
585 public final void set(long source, int maximumDigits)
\r
587 // This method does not expect a negative number. However,
\r
588 // "source" can be a Long.MIN_VALUE (-9223372036854775808),
\r
589 // if the number being formatted is a Long.MIN_VALUE. In that
\r
590 // case, it will be formatted as -Long.MIN_VALUE, a number
\r
591 // which is outside the legal range of a long, but which can
\r
592 // be represented by DigitList.
\r
593 // [NEW] Faster implementation
\r
595 if (source == Long.MIN_VALUE) {
\r
596 decimalAt = count = MAX_LONG_DIGITS;
\r
597 System.arraycopy(LONG_MIN_REP, 0, digits, 0, count);
\r
603 int left = MAX_LONG_DIGITS;
\r
605 while (source > 0) {
\r
606 digits[--left] = (byte) (((long) '0') + (source % 10));
\r
609 decimalAt = MAX_LONG_DIGITS-left;
\r
610 // Don't copy trailing zeros
\r
611 // we are guaranteed that there is at least one non-zero digit,
\r
612 // so we don't have to check lower bounds
\r
613 for (right = MAX_LONG_DIGITS - 1; digits[right] == (byte) '0'; --right) {}
\r
614 count = right - left + 1;
\r
615 System.arraycopy(digits, left, digits, 0, count);
\r
617 if (maximumDigits > 0) round(maximumDigits);
\r
621 * Set the digit list to a representation of the given BigInteger value.
\r
623 * @param source Value to be converted
\r
624 * @param maximumDigits The most digits which should be converted.
\r
625 * If maximumDigits is lower than the number of significant digits
\r
626 * in source, the representation will be rounded. Ignored if <= 0.
\r
628 public final void set(BigInteger source, int maximumDigits) {
\r
629 String stringDigits = source.toString();
\r
631 count = decimalAt = stringDigits.length();
\r
633 // Don't copy trailing zeros
\r
634 while (count > 1 && stringDigits.charAt(count - 1) == '0') --count;
\r
637 if (stringDigits.charAt(0) == '-') {
\r
643 ensureCapacity(count, 0);
\r
644 for (int i = 0; i < count; ++i) {
\r
645 digits[i] = (byte) stringDigits.charAt(i + offset);
\r
648 if (maximumDigits > 0) round(maximumDigits);
\r
652 * Internal method that sets this digit list to represent the
\r
653 * given value. The value is given as a String of the format
\r
654 * returned by BigDecimal.
\r
655 * @param stringDigits value to be represented with the following
\r
656 * syntax, expressed as a regular expression: -?\d*.?\d*
\r
657 * Must not be an empty string.
\r
658 * @param maximumDigits The most digits which should be converted.
\r
659 * If maximumDigits is lower than the number of significant digits
\r
660 * in source, the representation will be rounded. Ignored if <= 0.
\r
661 * @param fixedPoint If true, then maximumDigits is the maximum
\r
662 * fractional digits to be converted. If false, total digits.
\r
664 private void setBigDecimalDigits(String stringDigits,
\r
665 int maximumDigits, boolean fixedPoint) {
\r
666 //| // Find the first non-zero digit, the decimal, and the last non-zero digit.
\r
667 //| int first=-1, last=stringDigits.length()-1, decimal=-1;
\r
668 //| for (int i=0; (first<0 || decimal<0) && i<=last; ++i) {
\r
669 //| char c = stringDigits.charAt(i);
\r
670 //| if (c == '.') {
\r
672 //| } else if (first < 0 && (c >= '1' && c <= '9')) {
\r
677 //| if (first < 0) {
\r
682 //| // At this point we know there is at least one non-zero digit, so the
\r
683 //| // following loop is safe.
\r
685 //| char c = stringDigits.charAt(last);
\r
686 //| if (c != '0' && c != '.') {
\r
692 //| if (decimal < 0) {
\r
693 //| decimal = stringDigits.length();
\r
696 //| count = last - first;
\r
697 //| if (decimal < first || decimal > last) {
\r
700 //| decimalAt = decimal - first;
\r
701 //| if (decimalAt < 0) {
\r
705 //| ensureCapacity(count, 0);
\r
706 //| for (int i = 0; i < count; ++i) {
\r
707 //| digits[i] = (byte) stringDigits.charAt(first++);
\r
708 //| if (first == decimal) {
\r
713 // The maxDigits here could also be Integer.MAX_VALUE
\r
714 set(stringDigits, stringDigits.length());
\r
716 // Eliminate digits beyond maximum digits to be displayed.
\r
717 // Round up if appropriate.
\r
718 // {dlf} Some callers depend on passing '0' to round to mean 'don't round', but
\r
719 // rather than pass that information explicitly, we rely on some magic with maximumDigits
\r
720 // and decimalAt. Unfortunately, this is no good, because there are cases where maximumDigits
\r
721 // is zero and we do want to round, e.g. BigDecimal values -1 < x < 1. So since round
\r
722 // changed to perform rounding when the argument is 0, we now force the argument
\r
723 // to -1 in the situations where it matters.
\r
724 round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits == 0 ? -1 : maximumDigits);
\r
728 * Set the digit list to a representation of the given BigDecimal value.
\r
730 * @param source Value to be converted
\r
731 * @param maximumDigits The most digits which should be converted.
\r
732 * If maximumDigits is lower than the number of significant digits
\r
733 * in source, the representation will be rounded. Ignored if <= 0.
\r
734 * @param fixedPoint If true, then maximumDigits is the maximum
\r
735 * fractional digits to be converted. If false, total digits.
\r
737 public final void set(java.math.BigDecimal source,
\r
738 int maximumDigits, boolean fixedPoint) {
\r
739 setBigDecimalDigits(source.toString(), maximumDigits, fixedPoint);
\r
743 * Set the digit list to a representation of the given BigDecimal value.
\r
745 * @param source Value to be converted
\r
746 * @param maximumDigits The most digits which should be converted.
\r
747 * If maximumDigits is lower than the number of significant digits
\r
748 * in source, the representation will be rounded. Ignored if <= 0.
\r
749 * @param fixedPoint If true, then maximumDigits is the maximum
\r
750 * fractional digits to be converted. If false, total digits.
\r
752 public final void set(com.ibm.icu.math.BigDecimal source,
\r
753 int maximumDigits, boolean fixedPoint) {
\r
754 setBigDecimalDigits(source.toString(), maximumDigits, fixedPoint);
\r
758 * Returns true if this DigitList represents Long.MIN_VALUE;
\r
759 * false, otherwise. This is required so that getLong() works.
\r
761 private boolean isLongMIN_VALUE()
\r
763 if (decimalAt != count || count != MAX_LONG_DIGITS)
\r
766 for (int i = 0; i < count; ++i)
\r
768 if (digits[i] != LONG_MIN_REP[i]) return false;
\r
774 private static byte[] LONG_MIN_REP;
\r
778 // Store the representation of LONG_MIN without the leading '-'
\r
779 String s = Long.toString(Long.MIN_VALUE);
\r
780 LONG_MIN_REP = new byte[MAX_LONG_DIGITS];
\r
781 for (int i=0; i < MAX_LONG_DIGITS; ++i)
\r
783 LONG_MIN_REP[i] = (byte)s.charAt(i + 1);
\r
787 // Unused -- Alan 2003-05
\r
789 // * Return the floor of the log base 10 of a given double.
\r
790 // * This method compensates for inaccuracies which arise naturally when
\r
791 // * computing logs, and always give the correct value. The parameter
\r
792 // * must be positive and finite.
\r
794 // private static final int log10(double d)
\r
796 // // The reason this routine is needed is that simply taking the
\r
797 // // log and dividing by log10 yields a result which may be off
\r
798 // // by 1 due to rounding errors. For example, the naive log10
\r
799 // // of 1.0e300 taken this way is 299, rather than 300.
\r
800 // double log10 = Math.log(d) / LOG10;
\r
801 // int ilog10 = (int)Math.floor(log10);
\r
802 // // Positive logs could be too small, e.g. 0.99 instead of 1.0
\r
803 // if (log10 > 0 && d >= Math.pow(10, ilog10 + 1))
\r
807 // // Negative logs could be too big, e.g. -0.99 instead of -1.0
\r
808 // else if (log10 < 0 && d < Math.pow(10, ilog10))
\r
815 // private static final double LOG10 = Math.log(10.0);
\r
817 // (The following boilerplate methods are currently not called,
\r
818 // and cannot be called by tests since this class is
\r
819 // package-private. The methods may be useful in the future, so
\r
820 // we do not delete them. 2003-06-11 ICU 2.6 Alan)
\r
823 * equality test between two digit lists.
\r
825 public boolean equals(Object obj) {
\r
826 if (this == obj) // quick check
\r
828 if (!(obj instanceof DigitList)) // (1) same object?
\r
830 DigitList other = (DigitList) obj;
\r
831 if (count != other.count ||
\r
832 decimalAt != other.decimalAt)
\r
834 for (int i = 0; i < count; i++)
\r
835 if (digits[i] != other.digits[i])
\r
841 * Generates the hash code for the digit list.
\r
843 public int hashCode() {
\r
844 int hashcode = decimalAt;
\r
846 for (int i = 0; i < count; i++)
\r
847 hashcode = hashcode * 37 + digits[i];
\r
852 public String toString()
\r
854 if (isZero()) return "0";
\r
855 StringBuilder buf = new StringBuilder("0.");
\r
856 for (int i=0; i<count; ++i) buf.append((char)digits[i]);
\r
857 buf.append("x10^");
\r
858 buf.append(decimalAt);
\r
859 return buf.toString();
\r