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

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 1996, 2013, 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, 2014, 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
*** 288,316 **** */ final void set(boolean isNegative, double source, int maximumDigits, boolean fixedPoint) { FloatingDecimal.BinaryToASCIIConverter fdConverter = FloatingDecimal.getBinaryToASCIIConverter(source); boolean hasBeenRoundedUp = fdConverter.digitsRoundedUp(); ! boolean allDecimalDigits = fdConverter.decimalDigitsExact(); assert !fdConverter.isExceptional(); String digitsString = fdConverter.toJavaFormatString(); set(isNegative, digitsString, ! hasBeenRoundedUp, allDecimalDigits, maximumDigits, fixedPoint); } /** * Generate a representation of the form DDDDD, DDDDD.DDDDD, or * DDDDDE+/-DDDDD. ! * @param roundedUp Boolean value indicating if the s digits were rounded-up. ! * @param allDecimalDigits Boolean value indicating if the digits in s are ! * an exact decimal representation of the double that was passed. */ private void set(boolean isNegative, String s, ! boolean roundedUp, boolean allDecimalDigits, int maximumDigits, boolean fixedPoint) { this.isNegative = isNegative; int len = s.length(); char[] source = getDataChars(len); s.getChars(0, len, source, 0); --- 288,317 ---- */ final void set(boolean isNegative, double source, int maximumDigits, boolean fixedPoint) { FloatingDecimal.BinaryToASCIIConverter fdConverter = FloatingDecimal.getBinaryToASCIIConverter(source); boolean hasBeenRoundedUp = fdConverter.digitsRoundedUp(); ! boolean valueExactAsDecimal = fdConverter.decimalDigitsExact(); assert !fdConverter.isExceptional(); String digitsString = fdConverter.toJavaFormatString(); set(isNegative, digitsString, ! hasBeenRoundedUp, valueExactAsDecimal, maximumDigits, fixedPoint); } /** * Generate a representation of the form DDDDD, DDDDD.DDDDD, or * DDDDDE+/-DDDDD. ! * @param roundedUp whether or not rounding up has already happened. ! * @param valueExactAsDecimal whether or not collected digits provide ! * an exact decimal representation of the value. */ private void set(boolean isNegative, String s, ! boolean roundedUp, boolean valueExactAsDecimal, int maximumDigits, boolean fixedPoint) { + this.isNegative = isNegative; int len = s.length(); char[] source = getDataChars(len); s.getChars(0, len, source, 0);
*** 359,369 **** 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, roundedUp, allDecimalDigits)) { count = 1; ++decimalAt; digits[0] = '1'; } else { count = 0; --- 360,370 ---- 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, roundedUp, valueExactAsDecimal)) { count = 1; ++decimalAt; digits[0] = '1'; } else { count = 0;
*** 379,407 **** } // Eliminate digits beyond maximum digits to be displayed. // Round up if appropriate. round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits, ! roundedUp, allDecimalDigits); } /** * Round the representation to the given number of digits. * @param maximumDigits The maximum number of digits to be shown. ! * @param alreadyRounded Boolean indicating if rounding up already happened. ! * @param allDecimalDigits Boolean indicating if the digits provide an exact ! * representation of the value. * * Upon return, count will be less than or equal to maximumDigits. */ private final void round(int maximumDigits, boolean alreadyRounded, ! boolean allDecimalDigits) { // Eliminate digits beyond maximum digits to be displayed. // Round up if appropriate. if (maximumDigits >= 0 && maximumDigits < count) { ! if (shouldRoundUp(maximumDigits, alreadyRounded, allDecimalDigits)) { // 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; --- 380,409 ---- } // Eliminate digits beyond maximum digits to be displayed. // Round up if appropriate. round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits, ! roundedUp, valueExactAsDecimal); ! } /** * Round the representation to the given number of digits. * @param maximumDigits The maximum number of digits to be shown. ! * @param alreadyRounded whether or not rounding up has already happened. ! * @param valueExactAsDecimal whether or not collected digits provide ! * an exact decimal representation of the value. * * Upon return, count will be less than or equal to maximumDigits. */ private final void round(int maximumDigits, boolean alreadyRounded, ! boolean valueExactAsDecimal) { // Eliminate digits beyond maximum digits to be displayed. // Round up if appropriate. if (maximumDigits >= 0 && maximumDigits < count) { ! if (shouldRoundUp(maximumDigits, alreadyRounded, valueExactAsDecimal)) { // 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;
*** 438,455 **** * [bnf] * @param maximumDigits the number of digits to keep, from 0 to * <code>count-1</code>. 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 "#.#"). * @exception ArithmeticException if rounding is needed with rounding * mode being set to RoundingMode.UNNECESSARY * @return true if digit <code>maximumDigits-1</code> should be * incremented */ private boolean shouldRoundUp(int maximumDigits, boolean alreadyRounded, ! boolean allDecimalDigits) { if (maximumDigits < count) { /* * To avoid erroneous double-rounding or truncation when converting * a binary double value to text, information about the exactness * of the conversion result in FloatingDecimal, as well as any --- 440,460 ---- * [bnf] * @param maximumDigits the number of digits to keep, from 0 to * <code>count-1</code>. 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 "#.#"). + * @param alreadyRounded whether or not rounding up has already happened. + * @param valueExactAsDecimal whether or not collected digits provide + * an exact decimal representation of the value. * @exception ArithmeticException if rounding is needed with rounding * mode being set to RoundingMode.UNNECESSARY * @return true if digit <code>maximumDigits-1</code> should be * incremented */ private boolean shouldRoundUp(int maximumDigits, boolean alreadyRounded, ! boolean valueExactAsDecimal) { if (maximumDigits < count) { /* * To avoid erroneous double-rounding or truncation when converting * a binary double value to text, information about the exactness * of the conversion result in FloatingDecimal, as well as any
*** 488,498 **** * * - Other rounding modes are not impacted by these tie cases. * * - For other numbers that are always converted to exact digits * (like BigInteger, Long, ...), the passed alreadyRounded boolean ! * have to be set to false, and allDecimalDigits has to be set to * true in the upper DigitList call stack, providing the right state * for those situations.. */ switch(roundingMode) { --- 493,503 ---- * * - Other rounding modes are not impacted by these tie cases. * * - For other numbers that are always converted to exact digits * (like BigInteger, Long, ...), the passed alreadyRounded boolean ! * have to be set to false, and valueExactAsDecimal has to be set to * true in the upper DigitList call stack, providing the right state * for those situations.. */ switch(roundingMode) {
*** 518,563 **** return isNegative; } } break; case HALF_UP: - if (digits[maximumDigits] >= '5') { - // We should not round up if the rounding digits position is - // exactly the last index and if digits were already rounded. - if ((maximumDigits == (count - 1)) && - (alreadyRounded)) - return false; - - // Value was exactly at or was above tie. We must round up. - return true; - } - break; case HALF_DOWN: if (digits[maximumDigits] > '5') { return true; ! } else if (digits[maximumDigits] == '5' ) { ! if (maximumDigits == (count - 1)) { ! // The rounding position is exactly the last index. ! if (allDecimalDigits || alreadyRounded) ! /* FloatingDecimal rounded up (value was below tie), ! * or provided the exact list of digits (value was ! * an exact tie). We should not round up, following ! * the HALF_DOWN rounding rule. ! */ ! return false; ! else ! // Value was above the tie, we must round up. return true; } ! ! // We must round up if it gives a non null digit after '5'. ! for (int i=maximumDigits+1; i<count; ++i) { ! if (digits[i] != '0') { return true; } } } break; case HALF_EVEN: // Implement IEEE half-even rounding if (digits[maximumDigits] > '5') { return true; --- 523,567 ---- return isNegative; } } break; case HALF_UP: case HALF_DOWN: if (digits[maximumDigits] > '5') { + // Value is above tie ==> must round-up return true; ! } else if (digits[maximumDigits] == '5') { ! // Digit at rounding position is a '5'. Tie cases. ! if (maximumDigits != (count - 1)) { ! // There are remaining digits. Above tie => must round-up return true; } ! else { ! // Digit at rounding position is the last one ! ! if (valueExactAsDecimal) { ! // Exact binary representation. On the tie. ! // Apply rounding given by roundingMode. ! // I.e. we round-up only if roundingMode is HALF_UP. ! return roundingMode == RoundingMode.HALF_UP; ! } ! else { ! // Not an exact binary representation. ! if (alreadyRounded) { ! // Digit sequence rounded-up. Was below tie. ! // Don't round-up twice ! ! return false; ! } ! else { ! // Digit sequence truncated. Was above tie. ! // must round-up ! return true; } } } + } + // Digit at rounding position is < '5' ==> no round-up. + // Just let do the default, which is no round-up (thus break). break; case HALF_EVEN: // Implement IEEE half-even rounding if (digits[maximumDigits] > '5') { return true;
*** 567,577 **** if (alreadyRounded) // If FloatingDecimal rounded up (value was below tie), // then we should not round up again. return false; ! if (!allDecimalDigits) // Otherwise if the digits don't represent exact value, // value was above tie and FloatingDecimal truncated // digits to tie. We must round up. return true; else { --- 571,581 ---- if (alreadyRounded) // If FloatingDecimal rounded up (value was below tie), // then we should not round up again. return false; ! if (!valueExactAsDecimal) // Otherwise if the digits don't represent exact value, // value was above tie and FloatingDecimal truncated // digits to tie. We must round up. return true; else {