3789983e89
Reviewed-by: darcy, ihse
440 lines
18 KiB
Java
440 lines
18 KiB
Java
/*
|
|
* Copyright (c) 2012, 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.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/* @test
|
|
*
|
|
* @bug 7131459 8039915
|
|
* @summary test various situations of NumberFormat rounding when close to tie
|
|
* @author Olivier Lagneau
|
|
* @run main TieRoundingTest
|
|
*
|
|
*/
|
|
|
|
import java.math.BigDecimal;
|
|
import java.math.BigInteger;
|
|
import java.text.NumberFormat;
|
|
import java.text.DecimalFormat;
|
|
import java.math.RoundingMode;
|
|
import java.util.Locale;
|
|
|
|
public class TieRoundingTest {
|
|
|
|
static int testCounter = 0;
|
|
static int errorCounter = 0;
|
|
static boolean allPassed = true;
|
|
|
|
static void formatOutputTestDouble(NumberFormat nf,
|
|
double doubleToTest,
|
|
String tiePosition,
|
|
String inputDigits,
|
|
String expectedOutput) {
|
|
|
|
int mfd = nf.getMaximumFractionDigits();
|
|
RoundingMode rm = nf.getRoundingMode();
|
|
String result = nf.format(doubleToTest);
|
|
|
|
if (!result.equals(expectedOutput)) {
|
|
System.out.println();
|
|
System.out.println("========================================");
|
|
System.out.println("***Failure : error formatting value from string : " +
|
|
inputDigits);
|
|
System.out.println("NumberFormat pattern is : " +
|
|
((DecimalFormat ) nf).toPattern());
|
|
System.out.println("Maximum number of fractional digits : " + mfd);
|
|
System.out.println("Fractional rounding digit : " + (mfd + 1));
|
|
System.out.println("Position of value relative to tie : " + tiePosition);
|
|
System.out.println("Rounding Mode : " + rm);
|
|
System.out.println("BigDecimal output : " +
|
|
new BigDecimal(doubleToTest).toString());
|
|
System.out.println("FloatingDecimal output : " + doubleToTest);
|
|
System.out.println(
|
|
"Error. Formatted result different from expected." +
|
|
"\nExpected output is : \"" + expectedOutput + "\"" +
|
|
"\nFormated output is : \"" + result + "\"");
|
|
System.out.println("========================================");
|
|
System.out.println();
|
|
|
|
errorCounter++;
|
|
allPassed = false;
|
|
} else {
|
|
testCounter++;
|
|
System.out.println("\nSuccess for double value : " + doubleToTest + " :");
|
|
System.out.println(" Input digits :" + inputDigits +
|
|
", BigDecimal value : " +
|
|
new BigDecimal(doubleToTest).toString());
|
|
System.out.print(" Rounding mode: " + rm);
|
|
System.out.print(", fract digits : " + mfd);
|
|
System.out.print(", position : " + tiePosition + " tie");
|
|
System.out.print(", result : " + result);
|
|
System.out.println(", expected : " + expectedOutput);
|
|
}
|
|
}
|
|
|
|
static void formatOutputTestLong(NumberFormat nf,
|
|
long longToTest,
|
|
String tiePosition,
|
|
String inputDigits,
|
|
String expectedOutput) {
|
|
|
|
int mfd = nf.getMaximumFractionDigits();
|
|
RoundingMode rm = nf.getRoundingMode();
|
|
String result = nf.format(longToTest);
|
|
|
|
if (!result.equals(expectedOutput)) {
|
|
System.out.println();
|
|
System.out.println("========================================");
|
|
System.out.println("***Failure : error formatting value from string : " +
|
|
inputDigits);
|
|
System.out.println("NumberFormat pattern is : " +
|
|
((DecimalFormat ) nf).toPattern());
|
|
System.out.println("Maximum number of fractional digits : " + mfd);
|
|
System.out.println("Fractional rounding digit : " + (mfd + 1));
|
|
System.out.println("Position of value relative to tie : " + tiePosition);
|
|
System.out.println("Rounding Mode : " + rm);
|
|
System.out.println(
|
|
"Error. Formatted result different from expected." +
|
|
"\nExpected output is : \"" + expectedOutput + "\"" +
|
|
"\nFormated output is : \"" + result + "\"");
|
|
System.out.println("========================================");
|
|
System.out.println();
|
|
|
|
errorCounter++;
|
|
allPassed = false;
|
|
} else {
|
|
testCounter++;
|
|
System.out.print("Success. Long input :" + inputDigits);
|
|
System.out.print(", rounding : " + rm);
|
|
System.out.print(", fract digits : " + mfd);
|
|
System.out.print(", tie position : " + tiePosition);
|
|
System.out.println(", expected : " + expectedOutput);
|
|
|
|
}
|
|
}
|
|
|
|
static void formatOutputTestObject(NumberFormat nf,
|
|
Object someNumber,
|
|
String tiePosition,
|
|
String inputDigits,
|
|
String expectedOutput) {
|
|
|
|
int mfd = nf.getMaximumFractionDigits();
|
|
RoundingMode rm = nf.getRoundingMode();
|
|
String result = nf.format(someNumber);
|
|
|
|
if (!result.equals(expectedOutput)) {
|
|
System.out.println();
|
|
System.out.println("========================================");
|
|
System.out.println("***Failure : error formatting value from string : " +
|
|
inputDigits);
|
|
System.out.println("NumberFormat pattern is : " +
|
|
((DecimalFormat ) nf).toPattern());
|
|
System.out.println("Maximum number of fractional digits : " + mfd);
|
|
System.out.println("Fractional rounding digit : " + (mfd + 1));
|
|
System.out.println("Position of value relative to tie : " + tiePosition);
|
|
System.out.println("Rounding Mode : " + rm);
|
|
System.out.println("Number self output representation: " + someNumber);
|
|
System.out.println(
|
|
"Error. Formatted result different from expected." +
|
|
"\nExpected output is : \"" + expectedOutput + "\"" +
|
|
"\nFormated output is : \"" + result + "\"");
|
|
System.out.println("========================================");
|
|
System.out.println();
|
|
|
|
errorCounter++;
|
|
allPassed = false;
|
|
} else {
|
|
testCounter++;
|
|
System.out.print("Success. Number input :" + inputDigits);
|
|
System.out.print(", rounding : " + rm);
|
|
System.out.print(", fract digits : " + mfd);
|
|
System.out.print(", tie position : " + tiePosition);
|
|
System.out.println(", expected : " + expectedOutput);
|
|
}
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
|
|
// The 3 HALF_* rounding modes are impacted by bugs 7131459, 8039915.
|
|
// So we do not test the other rounding modes.
|
|
RoundingMode[] roundingModes = {
|
|
RoundingMode.HALF_DOWN,
|
|
RoundingMode.HALF_EVEN,
|
|
RoundingMode.HALF_UP
|
|
};
|
|
|
|
// Precise the relative position of input value against its closest tie.
|
|
// The double values tested below for 3 and 5 fractional digits must follow
|
|
// this scheme (position toward tie).
|
|
String[] tieRelativePositions = {
|
|
"below", "exact", "above",
|
|
"below", "exact", "above",
|
|
"below", "exact", "above",
|
|
"below", "above", "above",
|
|
"below", "below", "above",
|
|
"below", "exact", "above"
|
|
};
|
|
|
|
// =============== Testing double (and thus float) value cases =========
|
|
|
|
System.out.println("\n===== testing 3 digits rounding position =====");
|
|
double[] values3FractDigits = {
|
|
// unimpacting values close to tie, with less than 3 input fract digits
|
|
1.115d, 1.125d, 1.135d,
|
|
// HALF_* impacting close to tie values covering all 6 tie cases
|
|
0.3115d, 0.3125d, 0.3135d,
|
|
0.6865d, 0.6875d, 0.6885d,
|
|
// specific HALF_UP close to tie values
|
|
0.3124d, 0.3126d, 0.3128d,
|
|
// specific HALF_DOWN close to tie values
|
|
0.6864d, 0.6865d, 0.6868d,
|
|
// unimpacting values close to tie, with more than 3 input fract digits
|
|
1.46885d, 2.46875d, 1.46865d
|
|
};
|
|
|
|
String[] inputs3FractDigits = {
|
|
"1.115d", "1.125d", "1.135d",
|
|
"0.3115d", "0.3125d", "0.3135d",
|
|
"0.6865d", "0.6875d", "0.6885d",
|
|
"0.3124d", "0.3126d", "0.3128d",
|
|
"0.6864d", "0.6865d", "0.6868d",
|
|
"1.46885d", "2.46875d", "1.46865d"
|
|
};
|
|
|
|
String[][] expected3FractDigits = {
|
|
{"1.115", "1.125", "1.135",
|
|
"0.311", "0.312", "0.314",
|
|
"0.686", "0.687", "0.689",
|
|
"0.312", "0.313", "0.313",
|
|
"0.686", "0.686", "0.687",
|
|
"1.469", "2.469", "1.469"
|
|
},
|
|
{"1.115", "1.125", "1.135",
|
|
"0.311", "0.312", "0.314",
|
|
"0.686", "0.688", "0.689",
|
|
"0.312", "0.313", "0.313",
|
|
"0.686", "0.686", "0.687",
|
|
"1.469", "2.469", "1.469"
|
|
},
|
|
{"1.115", "1.125", "1.135",
|
|
"0.311", "0.313", "0.314",
|
|
"0.686", "0.688", "0.689",
|
|
"0.312", "0.313", "0.313",
|
|
"0.686", "0.686", "0.687",
|
|
"1.469", "2.469", "1.469"
|
|
},
|
|
};
|
|
|
|
|
|
for (int r = 0; r < roundingModes.length; r++) {
|
|
NumberFormat dfDefault = NumberFormat.getInstance(Locale.US);
|
|
RoundingMode rmode = roundingModes[r];
|
|
dfDefault.setRoundingMode(rmode);
|
|
System.out.println("\n----- Now checking " + rmode +
|
|
" rounding mode -----");
|
|
|
|
for (int i = 0; i < values3FractDigits.length; i++) {
|
|
double d = values3FractDigits[i];
|
|
String tiePosition = tieRelativePositions[i];
|
|
String input = inputs3FractDigits[i];
|
|
String expected = expected3FractDigits[r][i];
|
|
|
|
formatOutputTestDouble(dfDefault, d, tiePosition, input, expected);
|
|
}
|
|
}
|
|
|
|
System.out.println("\n===== testing 5 digits rounding position =====");
|
|
double[] values5FractDigits = {
|
|
// unimpacting values close to tie, with less than 5 input fract digits
|
|
1.3135d, 1.3125d, 1.3115d,
|
|
// HALF_* impacting values close to tie, covering all 6 cases
|
|
1.328115d, 1.328125d, 1.328135d,
|
|
1.796865d, 1.796875d, 1.796885d,
|
|
// specific HALF_UP close to tie values
|
|
1.328124d, 1.798876d, 1.796889d,
|
|
// specific HALF_DOWN close to tie values
|
|
1.328114d, 1.796865d, 1.328138d,
|
|
// unimpacting values close to tie, with more than 5 input fract digits
|
|
1.3281149999999d, 1.75390625d, 1.7968750000001d
|
|
};
|
|
|
|
String[] inputs5FractDigits = {
|
|
"1.3135d", "1.3125d", "1.3115d",
|
|
"1.328115d", "1.328125d", "1.328135d",
|
|
"1.796865d", "1.796875d", "1.796885d",
|
|
"1.328124d", "1.798876d", "1.796889d",
|
|
"1.328114d", "1.796865d", "1.328138d",
|
|
"1.3281149999999d", "1.75390625d", "1.7968750000001d"
|
|
};
|
|
|
|
String[][] expected5FractDigits = {
|
|
{"1.3135", "1.3125", "1.3115",
|
|
"1.32811", "1.32812", "1.32814",
|
|
"1.79686", "1.79687", "1.79689",
|
|
"1.32812", "1.79888", "1.79689",
|
|
"1.32811", "1.79686", "1.32814",
|
|
"1.32811", "1.75391", "1.79688"
|
|
},
|
|
{"1.3135", "1.3125", "1.3115",
|
|
"1.32811", "1.32812", "1.32814",
|
|
"1.79686", "1.79688", "1.79689",
|
|
"1.32812", "1.79888", "1.79689",
|
|
"1.32811", "1.79686", "1.32814",
|
|
"1.32811", "1.75391", "1.79688"
|
|
},
|
|
{"1.3135", "1.3125", "1.3115",
|
|
"1.32811", "1.32813", "1.32814",
|
|
"1.79686", "1.79688", "1.79689",
|
|
"1.32812", "1.79888", "1.79689",
|
|
"1.32811", "1.79686", "1.32814",
|
|
"1.32811", "1.75391", "1.79688"
|
|
}
|
|
};
|
|
|
|
|
|
for (int r = 0; r < roundingModes.length; r++) {
|
|
DecimalFormat df5 = (DecimalFormat) NumberFormat.getInstance(Locale.US);
|
|
RoundingMode rmode = roundingModes[r];
|
|
df5.setRoundingMode(rmode);
|
|
System.out.println("\n----- Now checking " + rmode +
|
|
" rounding mode -----");
|
|
df5.applyPattern("#,###.#####");
|
|
|
|
for (int i = 0; i < values5FractDigits.length; i++) {
|
|
double d = values5FractDigits[i];
|
|
String tiePosition = tieRelativePositions[i];
|
|
String input = inputs5FractDigits[i];
|
|
String expected = expected5FractDigits[r][i];
|
|
|
|
formatOutputTestDouble(df5, d, tiePosition, input, expected);
|
|
}
|
|
}
|
|
|
|
// ==================== Testing long value cases ====================
|
|
|
|
System.out.println("\n===== testing long values =====");
|
|
long l = 123456789012345L;
|
|
DecimalFormat dfLong = (DecimalFormat) NumberFormat.getInstance(Locale.US);
|
|
String tiePosition = "exact";
|
|
String input = "123456789012345L";
|
|
String expected = "123,456,789,012,345";
|
|
String result = dfLong.format(l);
|
|
formatOutputTestLong(dfLong, l, tiePosition, input, expected);
|
|
|
|
dfLong.applyPattern("0.###E0");
|
|
expected = "1.235E14";
|
|
formatOutputTestLong(dfLong, l, tiePosition, input, expected);
|
|
|
|
l = 123450000000000L;
|
|
input = "123450000000000L";
|
|
expected = "1.234E14";
|
|
formatOutputTestLong(dfLong, l, tiePosition, input, expected);
|
|
|
|
l = 987750000000000L;
|
|
input = "987750000000000L";
|
|
expected = "9.878E14";
|
|
formatOutputTestLong(dfLong, l, tiePosition, input, expected);
|
|
|
|
dfLong.applyPattern("#,###.0E0");
|
|
l = 987755000000000L;
|
|
input = "987755000000000L";
|
|
expected = "987.76E12";
|
|
|
|
formatOutputTestLong(dfLong, l, tiePosition, input, expected);
|
|
|
|
|
|
// ================= Testing BigInteger value cases =================
|
|
|
|
System.out.println("\n===== testing BigInteger values =====");
|
|
String stringValue = "12345678901234567890123456789012345";
|
|
BigInteger bi = new BigInteger(stringValue);
|
|
DecimalFormat dfBig = (DecimalFormat) NumberFormat.getInstance(Locale.US);
|
|
tiePosition = "exact";
|
|
input = stringValue;
|
|
expected = "12,345,678,901,234,567,890,123,456,789,012,345";
|
|
formatOutputTestObject(dfBig, bi, tiePosition, input, expected);
|
|
|
|
dfBig.applyPattern("0.###E0");
|
|
expected = "1.235E34";
|
|
formatOutputTestObject(dfBig, bi, tiePosition, input, expected);
|
|
|
|
stringValue = "12345000000000000000000000000000000";
|
|
input = stringValue;
|
|
bi = new BigInteger(stringValue);
|
|
expected = "1.234E34";
|
|
formatOutputTestObject(dfBig, bi, tiePosition, input, expected);
|
|
|
|
stringValue = "12345000000000000000000000000000001";
|
|
input = stringValue;
|
|
bi = new BigInteger(stringValue);
|
|
expected = "1.235E34";
|
|
formatOutputTestObject(dfBig, bi, tiePosition, input, expected);
|
|
|
|
stringValue = "98755000000000000000000000000000000";
|
|
input = stringValue;
|
|
bi = new BigInteger(stringValue);
|
|
expected = "9.876E34";
|
|
formatOutputTestObject(dfBig, bi, tiePosition, input, expected);
|
|
|
|
dfLong.applyPattern("#,###.0E0");
|
|
stringValue = "98775500000000000000000000000000000";
|
|
input = stringValue;
|
|
expected = "987.76E34";
|
|
|
|
// =============== Testing BigDecimal value cases ================
|
|
|
|
System.out.println("\n===== testing BigDecimal values =====");
|
|
dfBig = (DecimalFormat) NumberFormat.getInstance(Locale.US);
|
|
|
|
stringValue = "0.68850000000000000088817841970012523233890533447265625";
|
|
BigDecimal bd = new BigDecimal(stringValue);
|
|
tiePosition = "exact";
|
|
input = stringValue;
|
|
expected = "0.689";
|
|
formatOutputTestObject(dfBig, bd, tiePosition, input, expected);
|
|
|
|
stringValue = "0.31149999999999999911182158029987476766109466552734375";
|
|
bd = new BigDecimal(stringValue);
|
|
dfBig.applyPattern("#,##0.####");
|
|
tiePosition = "exact";
|
|
input = stringValue;
|
|
expected = "0.3115";
|
|
formatOutputTestObject(dfBig, bd, tiePosition, input, expected);
|
|
|
|
// ==================== Printing results and exiting ===================
|
|
|
|
System.out.println();
|
|
System.out.println("==> " + testCounter + " tests passed successfully");
|
|
System.out.println("==> " + errorCounter + " tests failed");
|
|
|
|
System.out.println();
|
|
if (allPassed) {
|
|
System.out.println(
|
|
"Success in formating all the values with the given parameters");
|
|
} else {
|
|
String s = "Test failed with " + errorCounter + " formating error(s).";
|
|
System.out.println(s);
|
|
throw new RuntimeException(s);
|
|
}
|
|
}
|
|
}
|