< prev index next >

src/java.base/share/classes/java/text/DecimalFormat.java

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 46,58 **** import java.math.RoundingMode; import java.text.spi.NumberFormatProvider; import java.util.ArrayList; import java.util.Currency; import java.util.Locale; - import java.util.ResourceBundle; - import java.util.concurrent.ConcurrentHashMap; - import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import sun.util.locale.provider.LocaleProviderAdapter; import sun.util.locale.provider.ResourceBundleBasedAdapter; --- 46,55 ----
*** 155,165 **** * 1,0000,0000. If you supply a pattern with multiple grouping characters, the * interval between the last one and the end of the integer is the one that is * used. So <code>"#,##,###,####"</code> == <code>"######,####"</code> == * <code>"##,####,####"</code>. * ! * <h4>Special Pattern Characters</h4> * * <p>Many characters in a pattern are taken literally; they are matched during * parsing and output unchanged during formatting. Special characters, on the * other hand, stand for other characters, strings, or classes of characters. * They must be quoted, unless noted otherwise, if they are to appear in the --- 152,162 ---- * 1,0000,0000. If you supply a pattern with multiple grouping characters, the * interval between the last one and the end of the integer is the one that is * used. So <code>"#,##,###,####"</code> == <code>"######,####"</code> == * <code>"##,####,####"</code>. * ! * <h4><a id="special_pattern_character">Special Pattern Characters</a></h4> * * <p>Many characters in a pattern are taken literally; they are matched during * parsing and output unchanged during formatting. Special characters, on the * other hand, stand for other characters, strings, or classes of characters. * They must be quoted, unless noted otherwise, if they are to appear in the
*** 570,587 **** * @param delegate notified of locations of sub fields * @exception ArithmeticException if rounding is needed with rounding * mode being set to RoundingMode.UNNECESSARY * @return The formatted number string */ ! private StringBuffer format(double number, StringBuffer result, FieldDelegate delegate) { ! if (Double.isNaN(number) || ! (Double.isInfinite(number) && multiplier == 0)) { ! int iFieldStart = result.length(); ! result.append(symbols.getNaN()); ! delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER, ! iFieldStart, result.length(), result); return result; } /* Detecting whether a double is negative is easy with the exception of * the value -0.0. This is a double which has a zero mantissa (and --- 567,581 ---- * @param delegate notified of locations of sub fields * @exception ArithmeticException if rounding is needed with rounding * mode being set to RoundingMode.UNNECESSARY * @return The formatted number string */ ! StringBuffer format(double number, StringBuffer result, FieldDelegate delegate) { ! ! boolean nanOrInfinity = handleNaN(number, result, delegate); ! if (nanOrInfinity) { return result; } /* Detecting whether a double is negative is easy with the exception of * the value -0.0. This is a double which has a zero mantissa (and
*** 597,606 **** --- 591,650 ---- if (multiplier != 1) { number *= multiplier; } + nanOrInfinity = handleInfinity(number, result, delegate, isNegative); + if (nanOrInfinity) { + return result; + } + + if (isNegative) { + number = -number; + } + + // at this point we are guaranteed a nonnegative finite number. + assert (number >= 0 && !Double.isInfinite(number)); + return doubleSubformat(number, result, delegate, isNegative); + } + + /** + * Checks if the given {@code number} is {@code Double.NaN}. if yes; + * appends the NaN symbol to the result string. The NaN string is + * determined by the DecimalFormatSymbols object. + * @param number the double number to format + * @param result where the text is to be appended + * @param delegate notified of locations of sub fields + * @return true, if number is a NaN; false otherwise + */ + boolean handleNaN(double number, StringBuffer result, + FieldDelegate delegate) { + if (Double.isNaN(number) + || (Double.isInfinite(number) && multiplier == 0)) { + int iFieldStart = result.length(); + result.append(symbols.getNaN()); + delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER, + iFieldStart, result.length(), result); + return true; + } + return false; + } + + /** + * Checks if the given {@code number} is {@code Double.NEGATIVE_INFINITY} + * or {@code Double.POSITIVE_INFINITY}. if yes; + * appends the infinity string to the result string. The infinity string is + * determined by the DecimalFormatSymbols object. + * @param number the double number to format + * @param result where the text is to be appended + * @param delegate notified of locations of sub fields + * @param isNegative whether the given {@code number} is negative + * @return true, if number is a {@code Double.NEGATIVE_INFINITY} or + * {@code Double.POSITIVE_INFINITY}; false otherwise + */ + boolean handleInfinity(double number, StringBuffer result, + FieldDelegate delegate, boolean isNegative) { if (Double.isInfinite(number)) { if (isNegative) { append(result, negativePrefix, delegate, getNegativePrefixFieldPositions(), Field.SIGN); } else {
*** 619,646 **** } else { append(result, positiveSuffix, delegate, getPositiveSuffixFieldPositions(), Field.SIGN); } ! return result; } ! ! if (isNegative) { ! number = -number; } ! // at this point we are guaranteed a nonnegative finite number. ! assert(number >= 0 && !Double.isInfinite(number)); ! ! synchronized(digitList) { int maxIntDigits = super.getMaximumIntegerDigits(); int minIntDigits = super.getMinimumIntegerDigits(); int maxFraDigits = super.getMaximumFractionDigits(); int minFraDigits = super.getMinimumFractionDigits(); ! digitList.set(isNegative, number, useExponentialNotation ? ! maxIntDigits + maxFraDigits : maxFraDigits, !useExponentialNotation); return subformat(result, delegate, isNegative, false, maxIntDigits, minIntDigits, maxFraDigits, minFraDigits); } } --- 663,687 ---- } else { append(result, positiveSuffix, delegate, getPositiveSuffixFieldPositions(), Field.SIGN); } ! return true; } ! return false; } ! StringBuffer doubleSubformat(double number, StringBuffer result, ! FieldDelegate delegate, boolean isNegative) { ! synchronized (digitList) { int maxIntDigits = super.getMaximumIntegerDigits(); int minIntDigits = super.getMinimumIntegerDigits(); int maxFraDigits = super.getMaximumFractionDigits(); int minFraDigits = super.getMinimumFractionDigits(); ! digitList.set(isNegative, number, useExponentialNotation ! ? maxIntDigits + maxFraDigits : maxFraDigits, !useExponentialNotation); return subformat(result, delegate, isNegative, false, maxIntDigits, minIntDigits, maxFraDigits, minFraDigits); } }
*** 681,691 **** * @return The formatted number string * @exception ArithmeticException if rounding is needed with rounding * mode being set to RoundingMode.UNNECESSARY * @see java.text.FieldPosition */ ! private StringBuffer format(long number, StringBuffer result, FieldDelegate delegate) { boolean isNegative = (number < 0); if (isNegative) { number = -number; } --- 722,732 ---- * @return The formatted number string * @exception ArithmeticException if rounding is needed with rounding * mode being set to RoundingMode.UNNECESSARY * @see java.text.FieldPosition */ ! StringBuffer format(long number, StringBuffer result, FieldDelegate delegate) { boolean isNegative = (number < 0); if (isNegative) { number = -number; }
*** 772,782 **** * @param delegate notified of locations of sub fields * @exception ArithmeticException if rounding is needed with rounding * mode being set to RoundingMode.UNNECESSARY * @return The formatted number string */ ! private StringBuffer format(BigDecimal number, StringBuffer result, FieldDelegate delegate) { if (multiplier != 1) { number = number.multiply(getBigDecimalMultiplier()); } boolean isNegative = number.signum() == -1; --- 813,823 ---- * @param delegate notified of locations of sub fields * @exception ArithmeticException if rounding is needed with rounding * mode being set to RoundingMode.UNNECESSARY * @return The formatted number string */ ! StringBuffer format(BigDecimal number, StringBuffer result, FieldDelegate delegate) { if (multiplier != 1) { number = number.multiply(getBigDecimalMultiplier()); } boolean isNegative = number.signum() == -1;
*** 833,843 **** * @return The formatted number string * @exception ArithmeticException if rounding is needed with rounding * mode being set to RoundingMode.UNNECESSARY * @see java.text.FieldPosition */ ! private StringBuffer format(BigInteger number, StringBuffer result, FieldDelegate delegate, boolean formatLong) { if (multiplier != 1) { number = number.multiply(getBigIntegerMultiplier()); } boolean isNegative = number.signum() == -1; --- 874,884 ---- * @return The formatted number string * @exception ArithmeticException if rounding is needed with rounding * mode being set to RoundingMode.UNNECESSARY * @see java.text.FieldPosition */ ! StringBuffer format(BigInteger number, StringBuffer result, FieldDelegate delegate, boolean formatLong) { if (multiplier != 1) { number = number.multiply(getBigIntegerMultiplier()); } boolean isNegative = number.signum() == -1;
*** 915,925 **** "Cannot format given Object as a Number"); } return delegate.getIterator(sb.toString()); } ! // ==== Begin fast-path formating logic for double ========================= /* Fast-path formatting will be used for format(double ...) methods iff a * number of conditions are met (see checkAndSetFastPathStatus()): * - Only if instance properties meet the right predefined conditions. * - The abs value of the double to format is <= Integer.MAX_VALUE. --- 956,966 ---- "Cannot format given Object as a Number"); } return delegate.getIterator(sb.toString()); } ! // ==== Begin fast-path formatting logic for double ========================= /* Fast-path formatting will be used for format(double ...) methods iff a * number of conditions are met (see checkAndSetFastPathStatus()): * - Only if instance properties meet the right predefined conditions. * - The abs value of the double to format is <= Integer.MAX_VALUE.
*** 1660,1696 **** fastPathData.firstUsedIndex, fastPathData.lastFreeIndex - fastPathData.firstUsedIndex); } // ======== End fast-path formating logic for double ========================= /** * Complete the formatting of a finite number. On entry, the digitList must * be filled in with the correct digits. */ private StringBuffer subformat(StringBuffer result, FieldDelegate delegate, boolean isNegative, boolean isInteger, int maxIntDigits, int minIntDigits, int maxFraDigits, int minFraDigits) { - // NOTE: This isn't required anymore because DigitList takes care of this. - // - // // 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, -fExponent == 2). If this - // // is more than the maximum fraction digits, then we have an underflow - // // for the printed representation. We recognize this here and set - // // the DigitList representation to zero in this situation. - // - // if (-digitList.decimalAt >= getMaximumFractionDigits()) - // { - // digitList.count = 0; - // } char zero = symbols.getZeroDigit(); int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero ! char grouping = symbols.getGroupingSeparator(); char decimal = isCurrencyFormat ? symbols.getMonetaryDecimalSeparator() : symbols.getDecimalSeparator(); /* Per bug 4147706, DecimalFormat must respect the sign of numbers which --- 1701,1787 ---- fastPathData.firstUsedIndex, fastPathData.lastFreeIndex - fastPathData.firstUsedIndex); } + /** + * Sets the {@code DigitList} used by this {@code DecimalFormat} + * instance. + * @param number the number to format + * @param isNegative true, if the number is negative; false otherwise + * @param maxDigits the max digits + */ + void setDigitList(Number number, boolean isNegative, int maxDigits) { + + if (number instanceof Double) { + digitList.set(isNegative, (Double) number, maxDigits, true); + } else if (number instanceof BigDecimal) { + digitList.set(isNegative, (BigDecimal) number, maxDigits, true); + } else if (number instanceof Long) { + digitList.set(isNegative, (Long) number, maxDigits); + } else if (number instanceof BigInteger) { + digitList.set(isNegative, (BigInteger) number, maxDigits); + } + } + // ======== End fast-path formating logic for double ========================= /** * Complete the formatting of a finite number. On entry, the digitList must * be filled in with the correct digits. */ private StringBuffer subformat(StringBuffer result, FieldDelegate delegate, boolean isNegative, boolean isInteger, int maxIntDigits, int minIntDigits, int maxFraDigits, int minFraDigits) { + // process prefix + if (isNegative) { + append(result, negativePrefix, delegate, + getNegativePrefixFieldPositions(), Field.SIGN); + } else { + append(result, positivePrefix, delegate, + getPositivePrefixFieldPositions(), Field.SIGN); + } + + // process number + subformatNumber(result, delegate, isNegative, isInteger, + maxIntDigits, minIntDigits, maxFraDigits, minFraDigits); + + // process suffix + if (isNegative) { + append(result, negativeSuffix, delegate, + getNegativeSuffixFieldPositions(), Field.SIGN); + } else { + append(result, positiveSuffix, delegate, + getPositiveSuffixFieldPositions(), Field.SIGN); + } + + return result; + } + + /** + * Subformats number part using the {@code DigitList} of this + * {@code DecimalFormat} instance. + * @param result where the text is to be appended + * @param delegate notified of the location of sub fields + * @param isNegative true, if the number is negative; false otherwise + * @param isInteger true, if the number is an integer; false otherwise + * @param maxIntDigits maximum integer digits + * @param minIntDigits minimum integer digits + * @param maxFraDigits maximum fraction digits + * @param minFraDigits minimum fraction digits + */ + void subformatNumber(StringBuffer result, FieldDelegate delegate, + boolean isNegative, boolean isInteger, + int maxIntDigits, int minIntDigits, + int maxFraDigits, int minFraDigits) { + + char grouping = symbols.getGroupingSeparator(); char zero = symbols.getZeroDigit(); int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero ! char decimal = isCurrencyFormat ? symbols.getMonetaryDecimalSeparator() : symbols.getDecimalSeparator(); /* Per bug 4147706, DecimalFormat must respect the sign of numbers which
*** 1701,1727 **** */ if (digitList.isZero()) { digitList.decimalAt = 0; // Normalize } - if (isNegative) { - append(result, negativePrefix, delegate, - getNegativePrefixFieldPositions(), Field.SIGN); - } else { - append(result, positivePrefix, delegate, - getPositivePrefixFieldPositions(), Field.SIGN); - } - if (useExponentialNotation) { int iFieldStart = result.length(); int iFieldEnd = -1; int fFieldStart = -1; // Minimum integer digits are handled in exponential format by // adjusting the exponent. For example, 0.01234 with 3 minimum // integer digits is "123.4E-4". - // Maximum integer digits are interpreted as indicating the // repeating range. This is useful for engineering notation, in // which the exponent is restricted to a multiple of 3. For // example, 0.01234 with 3 maximum integer digits is "12.34e-3". // If maximum integer digits are > 1 and are larger than --- 1792,1809 ----
*** 1957,1976 **** // Record field information for caller. delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION, fFieldStart, result.length(), result); } - - if (isNegative) { - append(result, negativeSuffix, delegate, - getNegativeSuffixFieldPositions(), Field.SIGN); - } else { - append(result, positiveSuffix, delegate, - getPositiveSuffixFieldPositions(), Field.SIGN); - } - - return result; } /** * Appends the String <code>string</code> to <code>result</code>. * <code>delegate</code> is notified of all the --- 2039,2048 ----
< prev index next >