diff options
7 files changed, 518 insertions, 125 deletions
diff --git a/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java b/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java index d1da72f..d46c2ec 100644 --- a/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java +++ b/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java @@ -20,6 +20,7 @@ import com.ibm.icu4jni.util.LocaleData; import java.math.BigDecimal; import java.math.BigInteger; +import java.math.RoundingMode; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import java.text.DecimalFormatSymbols; @@ -570,6 +571,21 @@ public class NativeDecimalFormat { } } + public void setRoundingMode(RoundingMode roundingMode, double roundingIncrement) { + final int nativeRoundingMode; + switch (roundingMode) { + case CEILING: nativeRoundingMode = 0; break; + case FLOOR: nativeRoundingMode = 1; break; + case DOWN: nativeRoundingMode = 2; break; + case UP: nativeRoundingMode = 3; break; + case HALF_EVEN: nativeRoundingMode = 4; break; + case HALF_DOWN: nativeRoundingMode = 5; break; + case HALF_UP: nativeRoundingMode = 6; break; + default: throw new AssertionError(); + } + setRoundingMode(addr, nativeRoundingMode, roundingIncrement); + } + private static native void applyPatternImpl(int addr, boolean localized, String pattern); private static native int cloneDecimalFormatImpl(int addr); private static native void closeDecimalFormatImpl(int addr); @@ -589,6 +605,7 @@ public class NativeDecimalFormat { String nan, char patternSeparator, char percent, char perMill, char zeroDigit); private static native void setSymbol(int addr, int symbol, String str); private static native void setAttribute(int addr, int symbol, int i); + private static native void setRoundingMode(int addr, int roundingMode, double roundingIncrement); private static native void setTextAttribute(int addr, int symbol, String str); private static native String toPatternImpl(int addr, boolean localized); } diff --git a/icu/src/main/native/NativeDecimalFormat.cpp b/icu/src/main/native/NativeDecimalFormat.cpp index 413ffdd..b62e5b1 100644 --- a/icu/src/main/native/NativeDecimalFormat.cpp +++ b/icu/src/main/native/NativeDecimalFormat.cpp @@ -103,10 +103,16 @@ static jint openDecimalFormatImpl(JNIEnv* env, jclass clazz, jstring pattern0, return static_cast<jint>(reinterpret_cast<uintptr_t>(fmt)); } -static void closeDecimalFormatImpl(JNIEnv *env, jclass clazz, jint addr) { +static void closeDecimalFormatImpl(JNIEnv* env, jclass, jint addr) { delete toDecimalFormat(addr); } +static void setRoundingMode(JNIEnv* env, jclass, jint addr, jint mode, jdouble increment) { + DecimalFormat* fmt = toDecimalFormat(addr); + fmt->setRoundingMode(static_cast<DecimalFormat::ERoundingMode>(mode)); + fmt->setRoundingIncrement(increment); +} + static void setSymbol(JNIEnv* env, jclass, jint addr, jint symbol, jstring s) { const UChar* chars = env->GetStringChars(s, NULL); const int32_t charCount = env->GetStringLength(s); @@ -593,6 +599,7 @@ static JNINativeMethod gMethods[] = { {"setAttribute", "(III)V", (void*) setAttribute}, {"setDecimalFormatSymbols", "(ILjava/lang/String;CCCLjava/lang/String;Ljava/lang/String;CCLjava/lang/String;CCCC)V", (void*) setDecimalFormatSymbols}, {"setSymbol", "(IILjava/lang/String;)V", (void*) setSymbol}, + {"setRoundingMode", "(IID)V", (void*) setRoundingMode}, {"setTextAttribute", "(IILjava/lang/String;)V", (void*) setTextAttribute}, {"toPatternImpl", "(IZ)Ljava/lang/String;", (void*) toPatternImpl}, }; diff --git a/luni/src/test/java/java/text/DecimalFormatTest.java b/luni/src/test/java/java/text/DecimalFormatTest.java index 6b2eb3d..c3a2721 100644 --- a/luni/src/test/java/java/text/DecimalFormatTest.java +++ b/luni/src/test/java/java/text/DecimalFormatTest.java @@ -19,10 +19,21 @@ package java.text; import junit.framework.Test; import junit.framework.TestSuite; +import java.math.BigDecimal; import java.math.BigInteger; +import java.math.RoundingMode; import java.util.Locale; public class DecimalFormatTest extends junit.framework.TestCase { + public void test_setMaximumFractionDigitsAffectsRoundingMode() throws Exception { + DecimalFormat df = (DecimalFormat) DecimalFormat.getInstance(Locale.US); + df.setMaximumFractionDigits(0); + df.setRoundingMode(RoundingMode.HALF_UP); + assertEquals("-0", df.format(-0.2)); + df.setMaximumFractionDigits(1); + assertEquals("-0.2", df.format(-0.2)); + } + // Android fails this test, truncating to 127 digits. public void test_setMaximumIntegerDigits() throws Exception { NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.US); @@ -34,4 +45,92 @@ public class DecimalFormatTest extends junit.framework.TestCase { assertEquals(309, numberFormat.format(123).length()); assertEquals(309, numberFormat.format(BigInteger.valueOf(123)).length()); } + + // Regression test for http://b/1897917: BigDecimal does not take into account multiplier. + public void testBigDecimalBug1897917() { + // For example. the BigDecimal 0.17 formatted in PercentInstance is 0% instead of 17%: + NumberFormat pf = NumberFormat.getPercentInstance(); + assertEquals("17%", pf.format(BigDecimal.valueOf(0.17))); + + // Test long decimal formatted in PercentInstance with various fractions. + String longDec = "11.2345678901234567890123456789012345678901234567890"; + BigDecimal bd = new BigDecimal(longDec); + assertBigDecimalWithFraction(bd, "1,123.46%", 2); + assertBigDecimalWithFraction(bd, "1,123.45678901%", 8); + assertBigDecimalWithFraction(bd, "1,123.4567890123%", 10); + assertBigDecimalWithFraction(bd, "1,123.45678901234567890123%", 20); + assertBigDecimalWithFraction(bd, "1,123.456789012345678901234567890123%", 30); + + // Test trailing zeros. + assertDecFmtWithMultiplierAndFraction("3333.33333333", 3, 4, "10,000"); + assertDecFmtWithMultiplierAndFraction("3333.33333333", -3, 4, "-10,000"); + assertDecFmtWithMultiplierAndFraction("0.00333333", 3, 4, "0.01"); + assertDecFmtWithMultiplierAndFraction("3330000000000000000000000000000000", 3, 4, + "9,990,000,000,000,000,000,000,000,000,000,000"); + } + + public void testBigDecimalTestBigIntWithMultiplier() { + // Big integer tests. + assertDecFmtWithMultiplierAndFraction("123456789012345", 10, 0, + "1,234,567,890,123,450"); + assertDecFmtWithMultiplierAndFraction("12345678901234567890", 10, 0, + "123,456,789,012,345,678,900"); + assertDecFmtWithMultiplierAndFraction("98765432109876543210987654321", 10, 0, + "987,654,321,098,765,432,109,876,543,210"); + + assertDecFmtWithMultiplierAndFraction("123456789012345", -10, 0, + "-1,234,567,890,123,450"); + assertDecFmtWithMultiplierAndFraction("12345678901234567890", -10, 0, + "-123,456,789,012,345,678,900"); + assertDecFmtWithMultiplierAndFraction("98765432109876543210987654321", -10, 0, + "-987,654,321,098,765,432,109,876,543,210"); + } + + public void testBigDecimalICUConsistency() { + DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(); + df.setMaximumFractionDigits(2); + df.setMultiplier(2); + assertEquals(df.format(BigDecimal.valueOf(0.16)), + df.format(BigDecimal.valueOf(0.16).doubleValue())); + assertEquals(df.format(BigDecimal.valueOf(0.0293)), + df.format(BigDecimal.valueOf(0.0293).doubleValue())); + assertEquals(df.format(BigDecimal.valueOf(0.006)), + df.format(BigDecimal.valueOf(0.006).doubleValue())); + assertEquals(df.format(BigDecimal.valueOf(0.00283)), + df.format(BigDecimal.valueOf(0.00283).doubleValue())); + assertEquals(df.format(BigDecimal.valueOf(1.60)), + df.format(BigDecimal.valueOf(1.60).doubleValue())); + assertEquals(df.format(BigDecimal.valueOf(15)), + df.format(BigDecimal.valueOf(15).doubleValue())); + assertEquals(df.format(BigDecimal.valueOf(170)), + df.format(BigDecimal.valueOf(170).doubleValue())); + assertEquals(df.format(BigDecimal.valueOf(234.56)), + df.format(BigDecimal.valueOf(234.56).doubleValue())); + assertEquals(df.format(BigDecimal.valueOf(0)), + df.format(BigDecimal.valueOf(0).doubleValue())); + assertEquals(df.format(BigDecimal.valueOf(-1)), + df.format(BigDecimal.valueOf(-1).doubleValue())); + assertEquals(df.format(BigDecimal.valueOf(-10000)), + df.format(BigDecimal.valueOf(-10000).doubleValue())); + assertEquals(df.format(BigDecimal.valueOf(-0.001)), + df.format(BigDecimal.valueOf(-0.001).doubleValue())); + assertEquals(df.format(BigDecimal.valueOf(1234567890.1234567)), + df.format(BigDecimal.valueOf(1234567890.1234567).doubleValue())); + assertEquals(df.format(BigDecimal.valueOf(1.234567E100)), + df.format(BigDecimal.valueOf(1.234567E100).doubleValue())); + } + + private void assertBigDecimalWithFraction(BigDecimal bd, String expectedResult, int fraction) { + NumberFormat pf = NumberFormat.getPercentInstance(); + pf.setMaximumFractionDigits(fraction); + assertEquals(expectedResult, pf.format(bd)); + } + + private void assertDecFmtWithMultiplierAndFraction(String value, int multiplier, int fraction, String expectedResult) { + DecimalFormat df = (DecimalFormat)NumberFormat.getInstance(); + df.setMultiplier(multiplier); + df.setMaximumFractionDigits(fraction); + BigDecimal d = new BigDecimal(value); + assertEquals(expectedResult, df.format(d)); + } } diff --git a/text/src/main/java/java/text/DecimalFormat.java b/text/src/main/java/java/text/DecimalFormat.java index 65d4d48..07047b2 100644 --- a/text/src/main/java/java/text/DecimalFormat.java +++ b/text/src/main/java/java/text/DecimalFormat.java @@ -27,6 +27,7 @@ import java.io.ObjectOutputStream; import java.io.ObjectStreamField; import java.math.BigDecimal; import java.math.BigInteger; +import java.math.RoundingMode; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Currency; @@ -553,6 +554,8 @@ public class DecimalFormat extends NumberFormat { private transient NativeDecimalFormat dform; + private transient RoundingMode roundingMode = RoundingMode.HALF_EVEN; + /** * Constructs a new {@code DecimalFormat} for formatting and parsing numbers * for the default locale. @@ -709,6 +712,21 @@ public class DecimalFormat extends NumberFormat { @Override public StringBuffer format(double value, StringBuffer buffer, FieldPosition position) { + // All float/double/Float/Double formatting ends up here... + if (roundingMode == RoundingMode.UNNECESSARY) { + // ICU4C doesn't support this rounding mode, so we have to fake it. + try { + setRoundingMode(RoundingMode.UP); + String upResult = format(value, new StringBuffer(), new FieldPosition(0)).toString(); + setRoundingMode(RoundingMode.DOWN); + String downResult = format(value, new StringBuffer(), new FieldPosition(0)).toString(); + if (!upResult.equals(downResult)) { + throw new ArithmeticException("rounding mode UNNECESSARY but rounding required"); + } + } finally { + setRoundingMode(RoundingMode.UNNECESSARY); + } + } return dform.format(value, buffer, position); } @@ -1040,6 +1058,8 @@ public class DecimalFormat extends NumberFormat { public void setMaximumFractionDigits(int value) { super.setMaximumFractionDigits(value); dform.setMaximumFractionDigits(getMaximumFractionDigits()); + // Changing the maximum fraction digits needs to update ICU4C's rounding configuration. + setRoundingMode(roundingMode); } /** @@ -1176,11 +1196,10 @@ public class DecimalFormat extends NumberFormat { new ObjectStreamField("negSuffixPattern", String.class), //$NON-NLS-1$ new ObjectStreamField("multiplier", int.class), //$NON-NLS-1$ new ObjectStreamField("groupingSize", byte.class), //$NON-NLS-1$ - // BEGIN android-added new ObjectStreamField("groupingUsed", boolean.class), //$NON-NLS-1$ - // END android-added new ObjectStreamField("decimalSeparatorAlwaysShown", boolean.class), //$NON-NLS-1$ new ObjectStreamField("parseBigDecimal", boolean.class), //$NON-NLS-1$ + new ObjectStreamField("roundingMode", RoundingMode.class), //$NON-NLS-1$ new ObjectStreamField("symbols", DecimalFormatSymbols.class), //$NON-NLS-1$ new ObjectStreamField("useExponentialNotation", boolean.class), //$NON-NLS-1$ new ObjectStreamField("minExponentDigits", byte.class), //$NON-NLS-1$ @@ -1220,6 +1239,7 @@ public class DecimalFormat extends NumberFormat { fields.put("decimalSeparatorAlwaysShown", dform .isDecimalSeparatorAlwaysShown()); fields.put("parseBigDecimal", parseBigDecimal); + fields.put("roundingMode", roundingMode); fields.put("symbols", symbols); fields.put("useExponentialNotation", false); fields.put("minExponentDigits", (byte) 0); @@ -1227,7 +1247,7 @@ public class DecimalFormat extends NumberFormat { fields.put("minimumIntegerDigits", dform.getMinimumIntegerDigits()); fields.put("maximumFractionDigits", dform.getMaximumFractionDigits()); fields.put("minimumFractionDigits", dform.getMinimumFractionDigits()); - fields.put("serialVersionOnStream", 3); + fields.put("serialVersionOnStream", 4); stream.writeFields(); } @@ -1243,9 +1263,7 @@ public class DecimalFormat extends NumberFormat { * if some class of serialized objects or fields cannot be found */ @SuppressWarnings("nls") - private void readObject(ObjectInputStream stream) throws IOException, - ClassNotFoundException { - + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { // BEGIN android-changed ObjectInputStream.GetField fields = stream.readFields(); this.symbols = (DecimalFormatSymbols) fields.get("symbols", null); @@ -1260,6 +1278,8 @@ public class DecimalFormat extends NumberFormat { dform.setGroupingUsed(fields.get("groupingUsed", true)); dform.setDecimalSeparatorAlwaysShown(fields.get("decimalSeparatorAlwaysShown", false)); + setRoundingMode((RoundingMode) fields.get("roundingMode", RoundingMode.HALF_EVEN)); + final int maximumIntegerDigits = fields.get("maximumIntegerDigits", 309); final int minimumIntegerDigits = fields.get("minimumIntegerDigits", 309); final int maximumFractionDigits = fields.get("maximumFractionDigits", 340); @@ -1285,4 +1305,29 @@ public class DecimalFormat extends NumberFormat { } // END android-changed } + + /** + * Returns the {@code RoundingMode} used by this {@code NumberFormat}. + * @since 1.6 + * @hide + */ + public RoundingMode getRoundingMode() { + return roundingMode; + } + + /** + * Sets the {@code RoundingMode} used by this {@code NumberFormat}. + * @since 1.6 + * @hide + */ + public void setRoundingMode(RoundingMode roundingMode) { + if (roundingMode == null) { + throw new NullPointerException(); + } + this.roundingMode = roundingMode; + if (roundingMode != RoundingMode.UNNECESSARY) { // ICU4C doesn't support UNNECESSARY. + double roundingIncrement = 1.0 / Math.pow(10, Math.max(0, getMaximumFractionDigits())); + dform.setRoundingMode(roundingMode, roundingIncrement); + } + } } diff --git a/text/src/main/java/java/text/Format.java b/text/src/main/java/java/text/Format.java index 18b0490..ff62856 100644 --- a/text/src/main/java/java/text/Format.java +++ b/text/src/main/java/java/text/Format.java @@ -66,9 +66,9 @@ public abstract class Format implements Serializable, Cloneable { private static final long serialVersionUID = -299282585814624189L; /** - * Constructs a new {@code Format} instance. + * Used by subclasses. This was public in Java 5. */ - public Format() { + protected Format() { } /** diff --git a/text/src/main/java/java/text/NumberFormat.java b/text/src/main/java/java/text/NumberFormat.java index 0ad6ac4..2bf898d 100644 --- a/text/src/main/java/java/text/NumberFormat.java +++ b/text/src/main/java/java/text/NumberFormat.java @@ -27,6 +27,7 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamField; import java.math.BigInteger; +import java.math.RoundingMode; import java.util.Currency; import java.util.Locale; @@ -164,9 +165,9 @@ public abstract class NumberFormat extends Format { maximumFractionDigits = 3, minimumFractionDigits = 0; /** - * Constructs a new instance of {@code NumberFormat}. + * Used by subclasses. This was public in Java 5. */ - public NumberFormat() { + protected NumberFormat() { } /** @@ -896,4 +897,25 @@ public abstract class NumberFormat extends Format { } } + /** + * Returns the {@code RoundingMode} used by this {@code NumberFormat}. The default + * implementation in {@code NumberFormat} throws {@code UnsupportedOperationException}. + * Subclasses for which a rounding mode is meaningful are expected to override this method. + * @since 1.6 + * @hide + */ + public RoundingMode getRoundingMode() { + throw new UnsupportedOperationException(); + } + + /** + * Sets the {@code RoundingMode} used by this {@code NumberFormat}. The default + * implementation in {@code NumberFormat} throws {@code UnsupportedOperationException}. + * Subclasses for which a rounding mode is meaningful are expected to override this method. + * @since 1.6 + * @hide + */ + public void setRoundingMode(RoundingMode roundingMode) { + throw new UnsupportedOperationException(); + } } diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java index 92aaf71..d7f0eaa 100644 --- a/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java +++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java @@ -35,6 +35,7 @@ import java.io.ObjectInputStream; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; +import java.math.RoundingMode; import java.text.AttributedCharacterIterator; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; @@ -2563,119 +2564,321 @@ public class DecimalFormatTest extends TestCase { DecimalFormat format = (DecimalFormat) DecimalFormat.getInstance(); format.setDecimalFormatSymbols(null); } - - private void assertBigDecimalWithFraction( - BigDecimal bd, - String expectedResult, - int fraction) { - NumberFormat pf = NumberFormat.getPercentInstance(); - pf.setMaximumFractionDigits(fraction); - assertEquals(expectedResult, pf.format(bd)); - } - - private void assertDecFmtWithMultiplierAndFraction( - String value, - int multiplier, - int fraction, - String expectedResult) { - - DecimalFormat df = (DecimalFormat)NumberFormat.getInstance(); - df.setMultiplier(multiplier); - df.setMaximumFractionDigits(fraction); - BigDecimal d = new BigDecimal(value); - assertEquals(expectedResult, df.format(d)); - } - - @TestTargetNew( - level = TestLevel.ADDITIONAL, - notes = "Regression test for some existing bugs and crashes", - method = "format", - args = { String.class, Object[].class } - ) - public void testBigDecimalBug1897917() { - // Bug1897917 : BigDecimal does not take into account multiplier. - // So the BigDecimal 0.17 formatted in PercentInstance is 0% instead of 17%. - - NumberFormat pf = NumberFormat.getPercentInstance(); - - // Test bug 1897917 case. - assertEquals("17%", pf.format(BigDecimal.valueOf(0.17))); - - // Test long decimal formatted in PercentInstance with various fractions. - String longDec = "11.2345678901234567890123456789012345678901234567890"; - BigDecimal bd = new BigDecimal(longDec); - assertBigDecimalWithFraction(bd, "1,123.46%", 2); - assertBigDecimalWithFraction(bd, "1,123.45678901%", 8); - assertBigDecimalWithFraction(bd, "1,123.4567890123%", 10); - assertBigDecimalWithFraction(bd, "1,123.45678901234567890123%", 20); - assertBigDecimalWithFraction(bd, "1,123.456789012345678901234567890123%", 30); - - // Test trailing zeros. - assertDecFmtWithMultiplierAndFraction("3333.33333333", 3, 4, "10,000"); - assertDecFmtWithMultiplierAndFraction("3333.33333333", -3, 4, "-10,000"); - assertDecFmtWithMultiplierAndFraction("0.00333333", 3, 4, "0.01"); - assertDecFmtWithMultiplierAndFraction("3330000000000000000000000000000000", 3, 4, - "9,990,000,000,000,000,000,000,000,000,000,000"); - } - - @TestTargetNew( - level = TestLevel.ADDITIONAL, - notes = "Regression test for some existing bugs and crashes", - method = "format", - args = { String.class, Object[].class } - ) - public void testBigDecimalTestBigIntWithMultiplier() { - // Big integer tests. - assertDecFmtWithMultiplierAndFraction("123456789012345", 10, 0, "1,234,567,890,123,450"); - assertDecFmtWithMultiplierAndFraction("12345678901234567890", 10, 0, - "123,456,789,012,345,678,900"); - assertDecFmtWithMultiplierAndFraction("98765432109876543210987654321", 10, 0, - "987,654,321,098,765,432,109,876,543,210"); - - assertDecFmtWithMultiplierAndFraction("123456789012345", -10, 0, "-1,234,567,890,123,450"); - assertDecFmtWithMultiplierAndFraction("12345678901234567890", -10, 0, - "-123,456,789,012,345,678,900"); - assertDecFmtWithMultiplierAndFraction("98765432109876543210987654321", -10, 0, - "-987,654,321,098,765,432,109,876,543,210"); - } - - @TestTargetNew( - level = TestLevel.ADDITIONAL, - notes = "Regression test for some existing bugs and crashes", - method = "format", - args = { String.class, Object[].class } - ) - public void testBigDecimalICUConsistency() { - DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(); - df.setMaximumFractionDigits(2); - df.setMultiplier(2); - assertEquals(df.format(BigDecimal.valueOf(0.16)), - df.format(BigDecimal.valueOf(0.16).doubleValue())); - assertEquals(df.format(BigDecimal.valueOf(0.0293)), - df.format(BigDecimal.valueOf(0.0293).doubleValue())); - assertEquals(df.format(BigDecimal.valueOf(0.006)), - df.format(BigDecimal.valueOf(0.006).doubleValue())); - assertEquals(df.format(BigDecimal.valueOf(0.00283)), - df.format(BigDecimal.valueOf(0.00283).doubleValue())); - assertEquals(df.format(BigDecimal.valueOf(1.60)), - df.format(BigDecimal.valueOf(1.60).doubleValue())); - assertEquals(df.format(BigDecimal.valueOf(15)), - df.format(BigDecimal.valueOf(15).doubleValue())); - assertEquals(df.format(BigDecimal.valueOf(170)), - df.format(BigDecimal.valueOf(170).doubleValue())); - assertEquals(df.format(BigDecimal.valueOf(234.56)), - df.format(BigDecimal.valueOf(234.56).doubleValue())); - assertEquals(df.format(BigDecimal.valueOf(0)), - df.format(BigDecimal.valueOf(0).doubleValue())); - assertEquals(df.format(BigDecimal.valueOf(-1)), - df.format(BigDecimal.valueOf(-1).doubleValue())); - assertEquals(df.format(BigDecimal.valueOf(-10000)), - df.format(BigDecimal.valueOf(-10000).doubleValue())); - assertEquals(df.format(BigDecimal.valueOf(-0.001)), - df.format(BigDecimal.valueOf(-0.001).doubleValue())); - assertEquals(df.format(BigDecimal.valueOf(1234567890.1234567)), - df.format(BigDecimal.valueOf(1234567890.1234567).doubleValue())); - assertEquals(df.format(BigDecimal.valueOf(1.234567E100)), - df.format(BigDecimal.valueOf(1.234567E100).doubleValue())); + + // BEGIN android-added: brought back from the harmony java6 branch. + public void test_SetRoudingMode_Ljava_math_RoundingMode() { + DecimalFormat decimalFormat = (DecimalFormat) DecimalFormat.getInstance(Locale.US); + // ignore the fraction part of a given value + decimalFormat.setMaximumFractionDigits(0); + + // set RoundingMode.HALF_DOWN of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.HALF_DOWN); + String result = decimalFormat.format(11.3); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_DOWN", "11", result); + + result = decimalFormat.format(11.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_DOWN", "11", result); + + result = decimalFormat.format(11.6); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_DOWN", "12", result); + + // set RoundingMode.CEILING of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.CEILING); + result = decimalFormat.format(11.3); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.CEILING", "12", result); + + result = decimalFormat.format(-11.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.CEILING", "-11", result); + + // set RoundingMode.DOWN of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.DOWN); + result = decimalFormat.format(11.3); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.DOWN", "11", result); + + result = decimalFormat.format(-11.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.DOWN", "-11", result); + + result = decimalFormat.format(0); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.DOWN", "0", result); + + // set RoundingMode.FLOOR of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.FLOOR); + result = decimalFormat.format(11.3); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.FLOOR", "11", result); + + result = decimalFormat.format(-11.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.FLOOR", "-12", result); + + result = decimalFormat.format(0); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.FLOOR", "0", result); + + // set RoundingMode.HALF_EVEN of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.HALF_EVEN); + result = decimalFormat.format(5.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_EVEN", "6", result); + + result = decimalFormat.format(-5.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_EVEN", "-6", result); + + result = decimalFormat.format(0.2); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_EVEN", "0", result); + + // set RoundingMode.HALF_UP of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.HALF_UP); + result = decimalFormat.format(5.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_UP", "6", result); + + result = decimalFormat.format(-5.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_UP", "-6", result); + + result = decimalFormat.format(0.2); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_UP", "0", result); + + // BEGIN android-changed: we're RI-compatible. + // the following assertion will fail on RI implementation, since the + // implementation of ICU and RI are not identical. + result = decimalFormat.format(-0.2); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_UP", "-0", result); + // END android-changed + + // set RoundingMode.UP of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.UP); + result = decimalFormat.format(5.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.UP", "6", result); + + result = decimalFormat.format(-5.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.UP", "-6", result); + + result = decimalFormat.format(0.2); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.UP", "1", result); + + result = decimalFormat.format(-0.2); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.UP", "-1", result); + + // set RoundingMode.UNNECESSARY of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.UNNECESSARY); + + try { + // when rounding is needed but RoundingMode is set to RoundingMode.UNNECESSARY, throw ArithmeticException + result = decimalFormat.format(5.5); + fail("ArithmeticException expected: RoundingMode.UNNECESSARY"); + } catch (ArithmeticException e) { + // expected + } + + result = decimalFormat.format(1.0); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.UNNECESSARY", "1", result); + + result = decimalFormat.format(-1.0); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.UNNECESSARY", "-1", result); + + try { + // when the given RoundingMode is null, throw NullPointerException + decimalFormat.setRoundingMode(null); + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // expected + } + + // set MaxFractionDigits to 3, test different DecimalFormat format + // function with differnt RoundingMode + decimalFormat.setMaximumFractionDigits(3); + + // set RoundingMode.HALF_DOWN of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.HALF_DOWN); + result = decimalFormat.format(11.5653); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_DOWN", "11.565", result); + + result = decimalFormat.format(11.5655); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_DOWN", "11.565", result); + + result = decimalFormat.format(11.5656); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_DOWN", "11.566", result); + + // set RoundingMode.CEILING of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.CEILING); + result = decimalFormat.format(11.5653); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.CEILING", "11.566", result); + + result = decimalFormat.format(-11.5653); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.CEILING", "-11.565", result); + + // set RoundingMode.DOWN of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.DOWN); + result = decimalFormat.format(11.5653); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.DOWN", "11.565", result); + + result = decimalFormat.format(-11.5653); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.DOWN", "-11.565", result); + + result = decimalFormat.format(0); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.DOWN", "0", result); + + // set RoundingMode.FLOOR of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.FLOOR); + result = decimalFormat.format(11.5653); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.FLOOR", "11.565", result); + + result = decimalFormat.format(-11.5655); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.FLOOR", "-11.566", result); + + result = decimalFormat.format(0); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.FLOOR", "0", result); + + // set RoundingMode.HALF_EVEN of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.HALF_EVEN); + result = decimalFormat.format(11.5653); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_EVEN", "11.565", result); + + result = decimalFormat.format(-11.5655); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_EVEN", "-11.566", result); + + result = decimalFormat.format(11.5656); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_EVEN", "11.566", result); + + // set RoundingMode.HALF_UP of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.HALF_UP); + result = decimalFormat.format(11.5653); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_UP", "11.565", result); + + result = decimalFormat.format(-11.5655); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_UP", "-11.566", result); + + result = decimalFormat.format(11.5656); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_UP", "11.566", result); + + // set RoundingMode.UP of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.UP); + result = decimalFormat.format(11.5653); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.UP", "11.566", result); + + result = decimalFormat.format(-11.5655); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.UP", "-11.566", result); + + // set RoundingMode.UNNECESSARY of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.UNNECESSARY); + result = decimalFormat.format(-11.565); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.UNNECESSARY", "-11.565", result); + + result = decimalFormat.format(11.565); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.UNNECESSARY", "11.565", result); + + // when setting MaxFractionDigits to negative value -2, default it as + // zero, test different DecimalFormat format + // function with differnt RoundingMode + decimalFormat.setMaximumFractionDigits(-2); + + // set RoundingMode.HALF_DOWN of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.HALF_DOWN); + result = decimalFormat.format(11.3); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_DOWN", "11", result); + + result = decimalFormat.format(11.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_DOWN", "11", result); + + result = decimalFormat.format(11.6); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_DOWN", "12", result); + + // set RoundingMode.CEILING of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.CEILING); + result = decimalFormat.format(11.3); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.CEILING", "12", result); + + result = decimalFormat.format(-11.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.CEILING", "-11", result); + + // set RoundingMode.DOWN of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.DOWN); + result = decimalFormat.format(11.3); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.DOWN", "11", result); + + result = decimalFormat.format(-11.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.DOWN", "-11", result); + + result = decimalFormat.format(0); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.DOWN", "0", result); + + // set RoundingMode.FLOOR of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.FLOOR); + result = decimalFormat.format(11.3); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.FLOOR", "11", result); + + result = decimalFormat.format(-11.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.FLOOR", "-12", result); + + result = decimalFormat.format(0); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.FLOOR", "0", result); + + // set RoundingMode.HALF_EVEN of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.HALF_EVEN); + result = decimalFormat.format(5.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_EVEN", "6", result); + + result = decimalFormat.format(-5.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_EVEN", "-6", result); + + result = decimalFormat.format(0.2); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_EVEN", "0", result); + + // set RoundingMode.HALF_UP of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.HALF_UP); + result = decimalFormat.format(5.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_UP", "6", result); + + result = decimalFormat.format(-5.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_UP", "-6", result); + + result = decimalFormat.format(0.2); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_UP", "0", result); + + result = decimalFormat.format(-0.2); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.HALF_UP", "-0", result); + + // set RoundingMode.UP of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.UP); + result = decimalFormat.format(5.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.UP", "6", result); + + result = decimalFormat.format(-5.5); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.UP", "-6", result); + + result = decimalFormat.format(0.2); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.UP", "1", result); + + result = decimalFormat.format(-0.2); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.UP", "-1", result); + + // set RoundingMode.UNNECESSARY of this DecimalFormat and test its + // behavior + decimalFormat.setRoundingMode(RoundingMode.UNNECESSARY); + + result = decimalFormat.format(1.0); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.UNNECESSARY", "1", result); + + result = decimalFormat.format(-1.0); + assertEquals("Incorrect RoundingMode behavior: RoundingMode.UNNECESSARY", "-1", result); } } |