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 {