FileDocCategorySizeDatePackage
DigitList.javaAPI DocphoneME MR2 API (J2ME)14472Wed May 02 18:00:46 BST 2007com.sun.j2me.global

DigitList

public final class DigitList extends Object
Digit List. Handles the transcoding between numeric values and strings of characters. Only handles non-negative numbers. The division of labor between DigitList and NumberFormat is that DigitList handles the radix 10 representation issues; numberFormat handles the locale-specific issues such as positive/negative, grouping, decimal point, currency, and so on. A DigitList is really a representation of a floating point value. It may be an integer value; we assume that a double has sufficient precision to represent all digits of a long. The DigitList representation consists of a string of characters, which are the digits radix 10, from '0' to '9'. It also has a radix 10 exponent associated with it.
see
NumberFormat

Fields Summary
public static final int
MAX_COUNT
The maximum number of significant digits in an IEEE 754 double, that is, in a Java double. This must not be increased, or garbage digits will be generated, and should not be decreased, or accuracy will be lost.
public static final int
DBL_DIG
Description of the Field.
public int
decimalAt
These data members are intentionally public and can be set directly. The value represented is given by placing the decimal point before digits[decimalAt]. If decimalAt is < 0, then leading zeros between the decimal point and the first nonzero digit are implied. If decimalAt is > count, then trailing zeros between the digits[count-1] and the decimal point are implied. Equivalently, the represented value is given by f * 10^decimalAt. Here f is a value 0.1 <= f < 1 arrived at by placing the digits in Digits to the right of the decimal. DigitList is normalized, so if it is non-zero, figits[0] is non-zero. We don't allow denormalized numbers because our exponent is effectively of unlimited magnitude. The count value contains the number of significant digits present in digits[]. Zero is represented by any DigitList with count == 0 or with each digits[i] for all i <= count == '0'.
public int
count
Counter of digits.
public char[]
digits
Array for digits.
private static final char[]
LONG_MIN_REP
The digit part of -9223372036854775808L
Constructors Summary
Methods Summary
public voidclear()
Clears out the digits. Use before appending them. Typically, you set a series of digits with append, then at the point you hit the decimal point, you set myDigitList.decimalAt = myDigitList.count; then go on appending digits.

        decimalAt = 0;
        count = 0;
    
public booleanisZero()
Return true if the represented number is zero.

return
The zero value



                        
       
        for (int i = 0; i < count; ++i) {
            if (digits[i] != '0") {
                return false;
            }
        }
        return true;
    
private static final intparseInt(char[] str, int offset)
Description of the Method

param
str Description of the Parameter
param
offset Description of the Parameter
return
Description of the Return Value

        char c;
        boolean positive = true;
        if ((c = str[offset]) == '-") {
            positive = false;
            offset++;
        } else if (c == '+") {
            offset++;
        }

        int value = 0;
        while (offset < str.length) {
            c = str[offset++];
            if (c >= '0" && c <= '9") {
                value = value * 10 + (c - '0");
            } else {
                break;
            }
        }
        return positive ? value : -value;
    
private final voidround(int maximumDigits)
Round the representation to the given number of digits.

param
maximumDigits The maximum number of digits to be shown. Upon return, count will be less than or equal to maximumDigits.

        // Eliminate digits beyond maximum digits to be displayed.
        // Round up if appropriate.
        if (maximumDigits >= 0 && maximumDigits < count) {
            if (shouldRoundUp(maximumDigits)) {
                // Rounding up involved incrementing digits from LSD to MSD.
                // In most cases this is simple, but in a worst case situation
                // (9999..99) we have to adjust the decimalAt value.
                for (; ; ) {
                    --maximumDigits;
                    if (maximumDigits < 0) {
                        // We have all 9's, so we increment to a single digit
                        // of one and adjust the exponent.
                        digits[0] = '1";
                        ++decimalAt;
                        maximumDigits = 0;
                        // Adjust the count
                        break;
                    }

                    ++digits[maximumDigits];
                    if (digits[maximumDigits] <= '9") {
                        break;
                    }
                    // digits[maximumDigits] = '0'; 
                    // Unnecessary since we'll truncate this
                }
                ++maximumDigits;
                // Increment for use as count
            }
            count = maximumDigits;

            // Eliminate trailing zeros.
            while (count > 1 && digits[count - 1] == '0") {
                --count;
            }
        }
    
public final voidset(double source, int maximumFractionDigits)
Set the digit list to a representation of the given double value. This method supports fixed-point notation.

param
source Value to be converted; must not be Inf, -Inf, Nan, or a value <= 0.
param
maximumFractionDigits The most fractional digits which should be converted.

        set(source, maximumFractionDigits, true);
    
final voidset(double source, int maximumDigits, boolean fixedPoint)
Set the digit list to a representation of the given double value. This method supports both fixed-point and exponential notation.

param
source Value to be converted; must not be Inf, -Inf, Nan, or a value <= 0.
param
maximumDigits The most fractional or total digits which should be converted.
param
fixedPoint If true, then maximumDigits is the maximum fractional digits to be converted. If false, total digits.

        if (source == 0) {
            source = 0;
        }
        // Generate a representation of the form DDDDD, DDDDD.DDDDD, or
        // DDDDDE+/-DDDDD.
        String sourceAsStr = Double.toString(source);
        char[] rep = sourceAsStr.toCharArray();
        int len = rep.length;
        
        decimalAt = -1;
        count = 0;
        int exponent = 0;
        // Number of zeros between decimal point and first non-zero digit after
        // decimal point, for numbers < 1.
        int leadingZerosAfterDecimal = 0;
        boolean nonZeroDigitSeen = false;

        for (int i = 0; i < len; ) {
            char c = rep[i++];
            if (c == '.") {
                decimalAt = count;
            } else if (c == 'e" || c == 'E") {
                exponent = parseInt(rep, i);
                break;
            } else if (count < MAX_COUNT) {
                if (!nonZeroDigitSeen) {
                    nonZeroDigitSeen = (c != '0");
                    if (!nonZeroDigitSeen && decimalAt != -1) {
                        ++leadingZerosAfterDecimal;
                    }
                }
                if (nonZeroDigitSeen) {
                    digits[count++] = c;
                }
            }
        }
        if (decimalAt == -1) {
            decimalAt = count;
        }
        if (nonZeroDigitSeen) {
            decimalAt += exponent - leadingZerosAfterDecimal;
        }

        if (fixedPoint) {
            // The negative of the exponent represents the number of leading
            // zeros between the decimal and the first non-zero digit, for
            // a value < 0.1 (e.g., for 0.00123, -decimalAt == 2).  If this
            // is more than the maximum fraction digits, then we have an 
            // underflow for the printed representation.
            if (-decimalAt > maximumDigits) {
                // Handle an underflow to zero when we round something like
                // 0.0009 to 2 fractional digits.
                count = 0;
                return;
            } else if (-decimalAt == maximumDigits) {
                // If we round 0.0009 to 3 fractional digits, then we have to
                // create a new one digit in the least significant location.
                if (shouldRoundUp(0)) {
                    count = 1;
                    ++decimalAt;
                    digits[0] = '1";
                } else {
                    count = 0;
                }
                return;
            }
            // else fall through
        }

        // Eliminate trailing zeros.
        while (count > 1 && digits[count - 1] == '0") {
            --count;
        }

        // Eliminate digits beyond maximum digits to be displayed.
        // Round up if appropriate.
        round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits);
    
public final voidset(long source, int maximumDigits)
Set the digit list to a representation of the given long value.

param
source Value to be converted; must be >= 0 or == Long.MIN_VALUE.
param
maximumDigits The most digits which should be converted. If maximumDigits is lower than the number of significant digits in source, the representation will be rounded. Ignored if <= 0.

        // This method does not expect a negative number. However,
        // "source" can be a Long.MIN_VALUE (-9223372036854775808),
        // if the number being formatted is a Long.MIN_VALUE.  In that
        // case, it will be formatted as -Long.MIN_VALUE, a number
        // which is outside the legal range of a long, but which can
        // be represented by DigitList.
        if (source <= 0) {
            if (source == Long.MIN_VALUE) {
                decimalAt = count = MAX_COUNT;
                System.arraycopy(LONG_MIN_REP, 0, digits, 0, count);
            } else {
                decimalAt = count = 0;
                // Values <= 0 format as zero
            }
        } else {
            // Rewritten to improve performance.  I used to call
            // Long.toString(), which was about 4x slower than this code.
            int left = MAX_COUNT;
            int right;
            while (source > 0) {
                digits[--left] = (char) ('0" + (source % 10));
                source /= 10;
            }
            decimalAt = MAX_COUNT - left;
            // Don't copy trailing zeros.  We are guaranteed that there is at
            // least one non-zero digit, so we don't have to check lower bounds.
            for (right = MAX_COUNT - 1; digits[right] == '0"; --right);
            
            count = right - left + 1;
            System.arraycopy(digits, left, digits, 0, count);
        }
        if (maximumDigits > 0) {
            round(maximumDigits);
        }
    
private booleanshouldRoundUp(int maximumDigits)
Return true if truncating the representation to the given number of digits will result in an increment to the last digit. This method implements half-even rounding, the default rounding mode. [bnf]

param
maximumDigits the number of digits to keep, from 0 to count-1 . If 0, then all digits are rounded away, and this method returns true if a one should be generated (e.g., formatting 0.09 with "#.#").
return
true if digit maximumDigits-1 should be incremented

        boolean increment = false;
        // Implement IEEE half-even rounding
        if (maximumDigits < count) {
            if (digits[maximumDigits] > '5") {
                return true;
            } else if (digits[maximumDigits] == '5") {
                for (int i = maximumDigits + 1; i < count; ++i) {
                    if (digits[i] != '0") {
                        return true;
                    }
                }
                return maximumDigits > 0 && 
                       (digits[maximumDigits - 1] % 2 != 0);
            }
        }
        return false;