diff options
author | Elliott Hughes <enh@google.com> | 2010-03-18 17:00:07 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2010-03-18 17:31:27 -0700 |
commit | 42db7d138547e3bba75cf6ed02b6a319e30004ae (patch) | |
tree | a03afd6a7aedd04aacb58d1e97f2f9ac51f21980 | |
parent | ee7ff7aae7187c37cf9e6f77018323ed782d8828 (diff) | |
download | libcore-42db7d138547e3bba75cf6ed02b6a319e30004ae.zip libcore-42db7d138547e3bba75cf6ed02b6a319e30004ae.tar.gz libcore-42db7d138547e3bba75cf6ed02b6a319e30004ae.tar.bz2 |
Add's Java 6's DecimalFormat.setRoundingMode (et cetera).
Format and NumberFormat's bogusly-public constructors became protected with
Java 6. DecimalFormat gained more control over rounding behavior. There's a
slight mismatch with our ICU4C-based implementation in that ICU4C doesn't
support RoundingMode.UNNECESSARY, so I've had to fake that (but I doubt it's
used much, if at all).
I've pulled out the obviously Android-specific tests from the harmony
DecimalFormatTest.java, but I've only brought back the rounding mode changes
from the current harmony code to avoid the new tests' dependencies. I've also
added one new test of my own, to check that setMaximumFractionDigits affects
rounding as it should (since the harmony tests don't test this, and it's
somewhat subtle).
Bug: 2497395
Change-Id: Ifafc8bb051e078ead988073281f5c33f0aeb130a
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); } } |