12d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// © 2016 and later: Unicode, Inc. and others. 22d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License 37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/* 47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 52391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius * Copyright (C) 1996-2015, International Business Machines Corporation and * 67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved. * 77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.text; 107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.math.BigInteger; 127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/** 147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DigitList</code> handles the transcoding between numeric values and 157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * strings of characters. It only represents non-negative numbers. The 167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * division of labor between <code>DigitList</code> and 177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DecimalFormat</code> is that <code>DigitList</code> handles the radix 187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 10 representation issues and numeric conversion, including rounding; 197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DecimalFormat</code> handles the locale-specific issues such as 207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * positive and negative representation, digit grouping, decimal point, 217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * currency, and so on. 227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>A <code>DigitList</code> is a representation of a finite numeric value. 247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DigitList</code> objects do not represent <code>NaN</code> or infinite 257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * values. A <code>DigitList</code> value can be converted to a 267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>BigDecimal</code> without loss of precision. Conversion to other 277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * numeric formats may involve loss of precision, depending on the specific 287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * value. 297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>The <code>DigitList</code> representation consists of a string of 317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * characters, which are the digits radix 10, from '0' to '9'. It also has a 327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * base 10 exponent associated with it. The value represented by a 337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DigitList</code> object can be computed by mulitplying the fraction 347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <em>f</em>, where 0 <= <em>f</em> < 1, derived by placing all the digits of 357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the list to the right of the decimal point, by 10^exponent. 367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see java.util.Locale 387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see java.text.Format 397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat 407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see DecimalFormat 417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see java.text.ChoiceFormat 427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see java.text.MessageFormat 437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @version 1.18 08/12/98 447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author Mark Davis, Alan Liu 457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * */ 467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertfinal class DigitList { 477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The maximum number of significant digits in an IEEE 754 double, that 497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is, in a Java double. This must not be increased, or garbage digits 507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * will be generated, and should not be decreased, or accuracy will be lost. 517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final int MAX_LONG_DIGITS = 19; // == Long.toString(Long.MAX_VALUE).length() 537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final int DBL_DIG = 17; 547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * These data members are intentionally public and can be set directly. 577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The value represented is given by placing the decimal point before 597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits[decimalAt]. If decimalAt is < 0, then leading zeros between 607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the decimal point and the first nonzero digit are implied. If decimalAt 617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is > count, then trailing zeros between the digits[count-1] and the 627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * decimal point are implied. 637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Equivalently, the represented value is given by f * 10^decimalAt. Here 657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * f is a value 0.1 <= f < 1 arrived at by placing the digits in Digits to 667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the right of the decimal. 677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DigitList is normalized, so if it is non-zero, figits[0] is non-zero. We 697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * don't allow denormalized numbers because our exponent is effectively of 707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * unlimited magnitude. The count value contains the number of significant 717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits present in digits[]. 727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Zero is represented by any DigitList with count == 0 or with each digits[i] 747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for all i <= count == '0'. 757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int decimalAt = 0; 777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int count = 0; 787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public byte[] digits = new byte[MAX_LONG_DIGITS]; 797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private final void ensureCapacity(int digitCapacity, int digitsToCopy) { 817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digitCapacity > digits.length) { 827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert byte[] newDigits = new byte[digitCapacity * 2]; 837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert System.arraycopy(digits, 0, newDigits, 0, digitsToCopy); 847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digits = newDigits; 857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Return true if the represented number is zero. 907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isZero() 927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i=0; i<count; ++i) if (digits[i] != '0') return false; 947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// Unused as of ICU 2.6 - alan 987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// /** 997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * Clears out the digits. 1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * Use before appending them. 1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * Typically, you set a series of digits with append, then at the point 1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * you hit the decimal point, you set myDigitList.decimalAt = myDigitList.count; 1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * then go on appending digits. 1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// */ 1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// public void clear () { 1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// decimalAt = 0; 1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// count = 0; 1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// } 1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Appends digits to the list. 1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void append (int digit) { 1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ensureCapacity(count+1, count); 1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digits[count++] = (byte) digit; 1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public byte getDigitValue(int i) { 1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (byte) (digits[i] - '0'); 1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Utility routine to get the value of the digit list 1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If (count == 0) this throws a NumberFormatException, which 1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * mimics Long.parseLong(). 1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public final double getDouble() { 1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count == 0) return 0.0; 1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder temp = new StringBuilder(count); 1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert temp.append('.'); 1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < count; ++i) temp.append((char)(digits[i])); 1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert temp.append('E'); 1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert temp.append(Integer.toString(decimalAt)); 1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return Double.valueOf(temp.toString()).doubleValue(); 1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // long value = Long.parseLong(temp.toString()); 1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // return (value * Math.pow(10, decimalAt - count)); 1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Utility routine to get the value of the digit list. 1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If (count == 0) this returns 0, unlike Long.parseLong(). 1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public final long getLong() { 1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // for now, simple implementation; later, do proper IEEE native stuff 1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count == 0) return 0; 1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We have to check for this, because this is the one NEGATIVE value 1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // we represent. If we tried to just pass the digits off to parseLong, 1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // we'd get a parse failure. 1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isLongMIN_VALUE()) return Long.MIN_VALUE; 1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder temp = new StringBuilder(count); 1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < decimalAt; ++i) 1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert temp.append((i < count) ? (char)(digits[i]) : '0'); 1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return Long.parseLong(temp.toString()); 1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Return a <code>BigInteger</code> representing the value stored in this 1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DigitList</code>. This method assumes that this object contains 1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * an integral value; if not, it will return an incorrect value. 1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * [bnf] 1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param isPositive determines the sign of the returned result 1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the value of this object as a <code>BigInteger</code> 1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public BigInteger getBigInteger(boolean isPositive) { 1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isZero()) return BigInteger.valueOf(0); 1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //Eclipse stated the following is "dead code" 1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*if (false) { 1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder stringRep = new StringBuilder(count); 1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!isPositive) { 1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stringRep.append('-'); 1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i=0; i<count; ++i) { 1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stringRep.append((char) digits[i]); 1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int d = decimalAt; 1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (d-- > count) { 1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stringRep.append('0'); 1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new BigInteger(stringRep.toString()); 1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else*/ { 1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int len = decimalAt > count ? decimalAt : count; 1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!isPositive) { 1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert len += 1; 1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char[] text = new char[len]; 1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int n = 0; 1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!isPositive) { 1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert text[0] = '-'; 1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < count; ++i) { 1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert text[i+1] = (char)digits[i]; 1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert n = count+1; 1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < count; ++i) { 2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert text[i] = (char)digits[i]; 2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert n = count; 2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = n; i < text.length; ++i) { 2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert text[i] = '0'; 2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new BigInteger(new String(text)); 2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String getStringRep(boolean isPositive) { 2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isZero()) return "0"; 2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder stringRep = new StringBuilder(count+1); 2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!isPositive) { 2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stringRep.append('-'); 2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int d = decimalAt; 2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (d < 0) { 2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stringRep.append('.'); 2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (d < 0) { 2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stringRep.append('0'); 2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++d; 2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert d = -1; 2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i=0; i<count; ++i) { 2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (d == i) { 2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stringRep.append('.'); 2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stringRep.append((char) digits[i]); 2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (d-- > count) { 2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stringRep.append('0'); 2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return stringRep.toString(); 2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Return an <code>ICU BigDecimal</code> representing the value stored in this 2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DigitList</code>. 2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * [bnf] 2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param isPositive determines the sign of the returned result 2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the value of this object as a <code>BigDecimal</code> 2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public com.ibm.icu.math.BigDecimal getBigDecimalICU(boolean isPositive) { 2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isZero()) { 2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return com.ibm.icu.math.BigDecimal.valueOf(0); 2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // if exponential notion is negative, 2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // we prefer to use BigDecimal constructor with scale, 2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // because it works better when extremely small value 2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // is used. See #5698. 2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long scale = (long)count - (long)decimalAt; 2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (scale > 0) { 2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int numDigits = count; 2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (scale > (long)Integer.MAX_VALUE) { 2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // try to reduce the scale 2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long numShift = scale - (long)Integer.MAX_VALUE; 2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (numShift < count) { 2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numDigits -= numShift; 2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // fallback to 0 2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new com.ibm.icu.math.BigDecimal(0); 2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder significantDigits = new StringBuilder(numDigits + 1); 2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!isPositive) { 2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert significantDigits.append('-'); 2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < numDigits; i++) { 2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert significantDigits.append((char)digits[i]); 2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert BigInteger unscaledVal = new BigInteger(significantDigits.toString()); 2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new com.ibm.icu.math.BigDecimal(unscaledVal, (int)scale); 2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new com.ibm.icu.math.BigDecimal(getStringRep(isPositive)); 2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Return whether or not this objects represented value is an integer. 2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * [bnf] 2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if the represented value of this object is an integer 2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isIntegral() { 2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Trim trailing zeros. This does not change the represented value. 2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (count > 0 && digits[count - 1] == (byte)'0') --count; 2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return count == 0 || decimalAt >= count; 2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// Unused as of ICU 2.6 - alan 2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// /** 2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * Return true if the number represented by this object can fit into 2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * a long. 2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// */ 2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// boolean fitsIntoLong(boolean isPositive) 2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// { 2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // Figure out if the result will fit in a long. We have to 2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // first look for nonzero digits after the decimal point; 3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // then check the size. If the digit count is 18 or less, then 3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // the value can definitely be represented as a long. If it is 19 3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // then it may be too large. 3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // Trim trailing zeros. This does not change the represented value. 3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// while (count > 0 && digits[count - 1] == (byte)'0') --count; 3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// if (count == 0) { 3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // Positive zero fits into a long, but negative zero can only 3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // be represented as a double. - bug 4162852 3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// return isPositive; 3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// } 3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// if (decimalAt < count || decimalAt > MAX_LONG_DIGITS) return false; 3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// if (decimalAt < MAX_LONG_DIGITS) return true; 3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // At this point we have decimalAt == count, and count == MAX_LONG_DIGITS. 3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // The number will overflow if it is larger than 9223372036854775807 3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // or smaller than -9223372036854775808. 3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// for (int i=0; i<count; ++i) 3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// { 3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// byte dig = digits[i], max = LONG_MIN_REP[i]; 3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// if (dig > max) return false; 3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// if (dig < max) return true; 3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// } 3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // At this point the first count digits match. If decimalAt is less 3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // than count, then the remaining digits are zero, and we return true. 3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// if (count < decimalAt) return true; 3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // Now we have a representation of Long.MIN_VALUE, without the leading 3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // negative sign. If this represents a positive value, then it does 3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // not fit; otherwise it fits. 3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// return !isPositive; 3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// } 3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// Unused as of ICU 2.6 - alan 3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// /** 3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * Set the digit list to a representation of the given double value. 3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * This method supports fixed-point notation. 3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * @param source Value to be converted; must not be Inf, -Inf, Nan, 3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * or a value <= 0. 3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * @param maximumFractionDigits The most fractional digits which should 3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * be converted. 3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// */ 3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// public final void set(double source, int maximumFractionDigits) 3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// { 3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// set(source, maximumFractionDigits, true); 3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// } 3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Set the digit list to a representation of the given double value. 3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This method supports both fixed-point and exponential notation. 3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param source Value to be converted; must not be Inf, -Inf, Nan, 3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * or a value <= 0. 3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param maximumDigits The most fractional or total digits which should 3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * be converted. 3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fixedPoint If true, then maximumDigits is the maximum 3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * fractional digits to be converted. If false, total digits. 3607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert final void set(double source, int maximumDigits, boolean fixedPoint) 3627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (source == 0) source = 0; 3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Generate a representation of the form DDDDD, DDDDD.DDDDD, or 3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // DDDDDE+/-DDDDD. 3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String rep = Double.toString(source); 3677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3682391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius didRound = false; 3692391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius 3707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert set(rep, MAX_LONG_DIGITS); 3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fixedPoint) { 3737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The negative of the exponent represents the number of leading 3747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // zeros between the decimal and the first non-zero digit, for 3757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // a value < 0.1 (e.g., for 0.00123, -decimalAt == 2). If this 3767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // is more than the maximum fraction digits, then we have an underflow 3777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // for the printed representation. 3787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (-decimalAt > maximumDigits) { 3797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = 0; 3807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return; 3817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (-decimalAt == maximumDigits) { 3827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (shouldRoundUp(0)) { 3837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = 1; 3847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++decimalAt; 3857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digits[0] = (byte)'1'; 3867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 3877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = 0; 3887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return; 3907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // else fall through 3927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Eliminate trailing zeros. 3957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (count > 1 && digits[count - 1] == '0') 3967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert --count; 3977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Eliminate digits beyond maximum digits to be displayed. 3997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Round up if appropriate. 4007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits == 0 ? -1 : maximumDigits); 4017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 4047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Given a string representation of the form DDDDD, DDDDD.DDDDD, 4057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * or DDDDDE+/-DDDDD, set this object's value to it. Ignore 4067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * any leading '-'. 4077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void set(String rep, int maxCount) { 4097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decimalAt = -1; 4107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = 0; 4117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int exponent = 0; 4127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Number of zeros between decimal point and first non-zero digit after 4137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // decimal point, for numbers < 1. 4147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int leadingZerosAfterDecimal = 0; 4157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean nonZeroDigitSeen = false; 4167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Skip over leading '-' 4177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i=0; 4187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (rep.charAt(i) == '-') { 4197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++i; 4207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (; i < rep.length(); ++i) { 4227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char c = rep.charAt(i); 4237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (c == '.') { 4247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decimalAt = count; 4257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (c == 'e' || c == 'E') { 4267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++i; 4277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Integer.parseInt doesn't handle leading '+' signs 4287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (rep.charAt(i) == '+') { 4297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++i; 4307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert exponent = Integer.valueOf(rep.substring(i)).intValue(); 4327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 4337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count < maxCount) { 4347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!nonZeroDigitSeen) { 4357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert nonZeroDigitSeen = (c != '0'); 4367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!nonZeroDigitSeen && decimalAt != -1) { 4377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++leadingZerosAfterDecimal; 4387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (nonZeroDigitSeen) { 4427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ensureCapacity(count+1, count); 4437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digits[count++] = (byte)c; 4447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (decimalAt == -1) { 4487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decimalAt = count; 4497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decimalAt += exponent - leadingZerosAfterDecimal; 4517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 4547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Return true if truncating the representation to the given number 4557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of digits will result in an increment to the last digit. This 4567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * method implements half-even rounding, the default rounding mode. 4577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * [bnf] 4587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param maximumDigits the number of digits to keep, from 0 to 4597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>count-1</code>. If 0, then all digits are rounded away, and 4607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * this method returns true if a one should be generated (e.g., formatting 4617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 0.09 with "#.#"). 4627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if digit <code>maximumDigits-1</code> should be 4637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * incremented 4647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean shouldRoundUp(int maximumDigits) { 4667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // variable not used boolean increment = false; 4677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Implement IEEE half-even rounding 4687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*Bug 4243108 4697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert format(0.0) gives "0.1" if preceded by parse("99.99") [Richard/GCL] 4707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (maximumDigits < count) { 4727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digits[maximumDigits] > '5') { 4737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 4747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (digits[maximumDigits] == '5' ) { 4757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i=maximumDigits+1; i<count; ++i) { 4767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digits[i] != '0') { 4777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 4787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return maximumDigits > 0 && (digits[maximumDigits-1] % 2 != 0); 4817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 4847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 4877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Round the representation to the given number of digits. 4887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param maximumDigits The maximum number of digits to be shown. 4897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Upon return, count will be less than or equal to maximumDigits. 4907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This now performs rounding when maximumDigits is 0, formerly it did not. 4917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public final void round(int maximumDigits) { 4937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Eliminate digits beyond maximum digits to be displayed. 4947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Round up if appropriate. 4957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [bnf] rewritten to fix 4179818 4967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (maximumDigits >= 0 && maximumDigits < count) { 4977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (shouldRoundUp(maximumDigits)) { 4987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Rounding up involves incrementing digits from LSD to MSD. 4997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // In most cases this is simple, but in a worst case situation 5007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // (9999..99) we have to adjust the decimalAt value. 5017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (;;) 5027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 5037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert --maximumDigits; 5047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (maximumDigits < 0) 5057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 5067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We have all 9's, so we increment to a single digit 5077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // of one and adjust the exponent. 5087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digits[0] = (byte) '1'; 5097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++decimalAt; 5107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maximumDigits = 0; // Adjust the count 5112391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius didRound = true; 5127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 5137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++digits[maximumDigits]; 5162391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius didRound = true; 5177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digits[maximumDigits] <= '9') break; 5187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // digits[maximumDigits] = '0'; // Unnecessary since we'll truncate this 5197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++maximumDigits; // Increment for use as count 5217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = maximumDigits; 5237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bug 4217661 DecimalFormat formats 1.001 to "1.00" instead of "1" 5257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Eliminate trailing zeros. [Richard/GCL] 5267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [dlf] moved outside if block, see ticket #6408 5277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (count > 1 && digits[count-1] == '0') { 5287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert --count; 5297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5322391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius // Value to indicate that rounding was done. 5332391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius private boolean didRound = false; 5342391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius 5352391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius /** 5362391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius * Indicates if last digit set was rounded or not. 5372391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius * true indicates it was rounded. 5382391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius * false indicates rounding has not been done. 5392391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius */ 5402391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius public boolean wasRounded() { 5412391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius return didRound; 5422391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius } 5432391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius 5447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Utility routine to set the value of the digit list from a long 5467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public final void set(long source) 5487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 5497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert set(source, 0); 5507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Set the digit list to a representation of the given long value. 5547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param source Value to be converted; must be >= 0 or == 5557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Long.MIN_VALUE. 5567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param maximumDigits The most digits which should be converted. 5577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If maximumDigits is lower than the number of significant digits 5587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in source, the representation will be rounded. Ignored if <= 0. 5597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public final void set(long source, int maximumDigits) 5617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 5627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // This method does not expect a negative number. However, 5637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "source" can be a Long.MIN_VALUE (-9223372036854775808), 5647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // if the number being formatted is a Long.MIN_VALUE. In that 5657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case, it will be formatted as -Long.MIN_VALUE, a number 5667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // which is outside the legal range of a long, but which can 5677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // be represented by DigitList. 5687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [NEW] Faster implementation 5692391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius didRound = false; 5702391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius 5717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (source <= 0) { 5727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (source == Long.MIN_VALUE) { 5737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decimalAt = count = MAX_LONG_DIGITS; 5747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert System.arraycopy(LONG_MIN_REP, 0, digits, 0, count); 5757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 5767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = 0; 5777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decimalAt = 0; 5787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 5807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int left = MAX_LONG_DIGITS; 5817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int right; 5827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (source > 0) { 5837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digits[--left] = (byte) (((long) '0') + (source % 10)); 5847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert source /= 10; 5857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decimalAt = MAX_LONG_DIGITS-left; 5877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Don't copy trailing zeros 5887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // we are guaranteed that there is at least one non-zero digit, 5897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // so we don't have to check lower bounds 5907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (right = MAX_LONG_DIGITS - 1; digits[right] == (byte) '0'; --right) {} 5917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = right - left + 1; 5927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert System.arraycopy(digits, left, digits, 0, count); 5937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (maximumDigits > 0) round(maximumDigits); 5957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Set the digit list to a representation of the given BigInteger value. 5997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * [bnf] 6007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param source Value to be converted 6017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param maximumDigits The most digits which should be converted. 6027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If maximumDigits is lower than the number of significant digits 6037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in source, the representation will be rounded. Ignored if <= 0. 6047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public final void set(BigInteger source, int maximumDigits) { 6067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String stringDigits = source.toString(); 6077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = decimalAt = stringDigits.length(); 6092391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius didRound = false; 6102391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius 6117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Don't copy trailing zeros 6127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (count > 1 && stringDigits.charAt(count - 1) == '0') --count; 6137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int offset = 0; 6157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (stringDigits.charAt(0) == '-') { 6167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++offset; 6177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert --count; 6187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert --decimalAt; 6197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ensureCapacity(count, 0); 6227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < count; ++i) { 6237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digits[i] = (byte) stringDigits.charAt(i + offset); 6247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (maximumDigits > 0) round(maximumDigits); 6277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 6307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Internal method that sets this digit list to represent the 6317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * given value. The value is given as a String of the format 6327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * returned by BigDecimal. 6337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param stringDigits value to be represented with the following 6347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * syntax, expressed as a regular expression: -?\d*.?\d* 6357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Must not be an empty string. 6367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param maximumDigits The most digits which should be converted. 6377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If maximumDigits is lower than the number of significant digits 6387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in source, the representation will be rounded. Ignored if <= 0. 6397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fixedPoint If true, then maximumDigits is the maximum 6407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * fractional digits to be converted. If false, total digits. 6417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void setBigDecimalDigits(String stringDigits, 6437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int maximumDigits, boolean fixedPoint) { 6447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| // Find the first non-zero digit, the decimal, and the last non-zero digit. 6457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| int first=-1, last=stringDigits.length()-1, decimal=-1; 6467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| for (int i=0; (first<0 || decimal<0) && i<=last; ++i) { 6477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| char c = stringDigits.charAt(i); 6487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| if (c == '.') { 6497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| decimal = i; 6507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| } else if (first < 0 && (c >= '1' && c <= '9')) { 6517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| first = i; 6527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| } 6537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| } 6547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| 6557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| if (first < 0) { 6567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| clear(); 6577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| return; 6587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| } 6597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| 6607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| // At this point we know there is at least one non-zero digit, so the 6617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| // following loop is safe. 6627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| for (;;) { 6637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| char c = stringDigits.charAt(last); 6647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| if (c != '0' && c != '.') { 6657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| break; 6667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| } 6677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| --last; 6687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| } 6697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| 6707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| if (decimal < 0) { 6717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| decimal = stringDigits.length(); 6727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| } 6737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| 6747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| count = last - first; 6757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| if (decimal < first || decimal > last) { 6767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| ++count; 6777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| } 6787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| decimalAt = decimal - first; 6797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| if (decimalAt < 0) { 6807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| ++decimalAt; 6817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| } 6827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| 6837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| ensureCapacity(count, 0); 6847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| for (int i = 0; i < count; ++i) { 6857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| digits[i] = (byte) stringDigits.charAt(first++); 6867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| if (first == decimal) { 6877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| ++first; 6887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| } 6897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//| } 6907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6912391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius didRound = false; 6922391a0f7a931341cbf7360f6870d3b4b2d7f5038Craig Cornelius 6937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The maxDigits here could also be Integer.MAX_VALUE 6947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert set(stringDigits, stringDigits.length()); 6957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Eliminate digits beyond maximum digits to be displayed. 6977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Round up if appropriate. 6987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // {dlf} Some callers depend on passing '0' to round to mean 'don't round', but 6997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // rather than pass that information explicitly, we rely on some magic with maximumDigits 7007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // and decimalAt. Unfortunately, this is no good, because there are cases where maximumDigits 7017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // is zero and we do want to round, e.g. BigDecimal values -1 < x < 1. So since round 7027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // changed to perform rounding when the argument is 0, we now force the argument 7037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // to -1 in the situations where it matters. 7047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits == 0 ? -1 : maximumDigits); 7057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 7087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Set the digit list to a representation of the given BigDecimal value. 7097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * [bnf] 7107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param source Value to be converted 7117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param maximumDigits The most digits which should be converted. 7127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If maximumDigits is lower than the number of significant digits 7137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in source, the representation will be rounded. Ignored if <= 0. 7147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fixedPoint If true, then maximumDigits is the maximum 7157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * fractional digits to be converted. If false, total digits. 7167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public final void set(java.math.BigDecimal source, 7187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int maximumDigits, boolean fixedPoint) { 7197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setBigDecimalDigits(source.toString(), maximumDigits, fixedPoint); 7207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 7237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Set the digit list to a representation of the given BigDecimal value. 7247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * [bnf] 7257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param source Value to be converted 7267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param maximumDigits The most digits which should be converted. 7277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If maximumDigits is lower than the number of significant digits 7287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in source, the representation will be rounded. Ignored if <= 0. 7297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fixedPoint If true, then maximumDigits is the maximum 7307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * fractional digits to be converted. If false, total digits. 7317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public final void set(com.ibm.icu.math.BigDecimal source, 7337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int maximumDigits, boolean fixedPoint) { 7347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setBigDecimalDigits(source.toString(), maximumDigits, fixedPoint); 7357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 7387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns true if this DigitList represents Long.MIN_VALUE; 7397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * false, otherwise. This is required so that getLong() works. 7407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean isLongMIN_VALUE() 7427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 7437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (decimalAt != count || count != MAX_LONG_DIGITS) 7447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 7457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < count; ++i) 7477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 7487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digits[i] != LONG_MIN_REP[i]) return false; 7497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 7527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static byte[] LONG_MIN_REP; 7557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static 7577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 7587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Store the representation of LONG_MIN without the leading '-' 7597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String s = Long.toString(Long.MIN_VALUE); 7607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert LONG_MIN_REP = new byte[MAX_LONG_DIGITS]; 7617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i=0; i < MAX_LONG_DIGITS; ++i) 7627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 7637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert LONG_MIN_REP[i] = (byte)s.charAt(i + 1); 7647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// Unused -- Alan 2003-05 7687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// /** 7697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * Return the floor of the log base 10 of a given double. 7707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * This method compensates for inaccuracies which arise naturally when 7717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * computing logs, and always give the correct value. The parameter 7727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * must be positive and finite. 7737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// */ 7747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// private static final int log10(double d) 7757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// { 7767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // The reason this routine is needed is that simply taking the 7777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // log and dividing by log10 yields a result which may be off 7787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // by 1 due to rounding errors. For example, the naive log10 7797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // of 1.0e300 taken this way is 299, rather than 300. 7807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// double log10 = Math.log(d) / LOG10; 7817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// int ilog10 = (int)Math.floor(log10); 7827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // Positive logs could be too small, e.g. 0.99 instead of 1.0 7837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// if (log10 > 0 && d >= Math.pow(10, ilog10 + 1)) 7847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// { 7857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// ++ilog10; 7867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// } 7877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// // Negative logs could be too big, e.g. -0.99 instead of -1.0 7887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// else if (log10 < 0 && d < Math.pow(10, ilog10)) 7897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// { 7907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// --ilog10; 7917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// } 7927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// return ilog10; 7937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// } 7947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 7957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// private static final double LOG10 = Math.log(10.0); 7967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 7987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * equality test between two digit lists. 7997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean equals(Object obj) { 8017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (this == obj) // quick check 8027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 8037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!(obj instanceof DigitList)) // (1) same object? 8047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 8057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DigitList other = (DigitList) obj; 8067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count != other.count || 8077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decimalAt != other.decimalAt) 8087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 8097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < count; i++) 8107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digits[i] != other.digits[i]) 8117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 8127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 8137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Generates the hash code for the digit list. 8177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int hashCode() { 8197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int hashcode = decimalAt; 8207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < count; i++) 8227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert hashcode = hashcode * 37 + digits[i]; 8237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return hashcode; 8257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String toString() 8287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 8297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isZero()) return "0"; 8307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder buf = new StringBuilder("0."); 8317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i=0; i<count; ++i) buf.append((char)digits[i]); 8327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append("x10^"); 8337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(decimalAt); 8347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return buf.toString(); 8357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert} 837