ICU-5491 put back functionality for negative multipliers, fixed up some code to handle them correctly, and added tests.

X-SVN-Rev: 23228
This commit is contained in:
Andrew J Macheret 2008-01-14 20:10:54 +00:00
parent 46eb0f1212
commit 6c2161e7bd
3 changed files with 64 additions and 12 deletions

View File

@ -641,7 +641,8 @@ DecimalFormat::format(int64_t number,
// instead, trading off accuracy for range.
if (fRoundingIncrement != NULL
|| (fMultiplier != 0 && (number > (U_INT64_MAX / fMultiplier)
|| number < (U_INT64_MIN / fMultiplier))))
|| number < (U_INT64_MIN / fMultiplier)
|| number == U_INT64_MIN && fMultiplier < 0)))
{
digits.set(((double)number) * fMultiplier,
precision(FALSE),
@ -682,6 +683,13 @@ DecimalFormat::format( double number,
return appendTo;
}
// Do this BEFORE checking to see if value is infinite or negative! Sets the
// begin and end index to be length of the string composed of
// localized name of Infinite and the positive/negative localized
// signs.
number *= fMultiplier;
/* Detecting whether a double is negative is easy with the exception of
* the value -0.0. This is a double which has a zero mantissa (and
* exponent), but a negative sign bit. It is semantically distinct from
@ -694,13 +702,6 @@ DecimalFormat::format( double number,
*/
UBool isNegative = uprv_isNegative(number);
// Do this BEFORE checking to see if value is infinite! Sets the
// begin and end index to be length of the string composed of
// localized name of Infinite and the positive/negative localized
// signs.
number *= fMultiplier;
// Apply rounding after multiplier
if (fRoundingIncrement != NULL) {
if (isNegative) // For rounding in the correct direction
@ -2100,10 +2101,10 @@ int32_t DecimalFormat::getMultiplier() const
void
DecimalFormat::setMultiplier(int32_t newValue)
{
// if (newValue <= 0) {
// throw new IllegalArgumentException("Bad multiplier: " + newValue);
// }
if (newValue > 0) {
// if (newValue == 0) {
// throw new IllegalArgumentException("Bad multiplier: " + newValue);
// }
if (newValue != 0) {
fMultiplier = newValue;
}
// else No way to return an error.

View File

@ -85,6 +85,7 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n
CASE(33,TestHostClone);
CASE(34,TestCurrencyFormat);
CASE(35,TestRounding);
CASE(36,TestNonpositiveMultiplier);
default: name = ""; break;
}
}
@ -2409,4 +2410,52 @@ double NumberFormatTest::checkRound(DecimalFormat* df, double iValue, double las
return lastParsed;
}
void NumberFormatTest::TestNonpositiveMultiplier() {
UErrorCode status = U_ZERO_ERROR;
DecimalFormatSymbols US(Locale::getUS(), status);
CHECK(status, "DecimalFormatSymbols constructor");
DecimalFormat df(UnicodeString("0"), US, status);
CHECK(status, "DecimalFormat(0)");
// test zero multiplier
int32_t mult = df.getMultiplier();
df.setMultiplier(0);
if (df.getMultiplier() != mult) {
errln("DecimalFormat.setMultiplier(0) did not ignore its zero input");
}
// test negative multiplier
df.setMultiplier(-1);
if (df.getMultiplier() != -1) {
errln("DecimalFormat.setMultiplier(-1) ignored its negative input");
return;
}
expect(df, "1122.123", -1122.123);
expect(df, "-1122.123", 1122.123);
expect(df, "1.2", -1.2);
expect(df, "-1.2", 1.2);
// TODO: comment once BigInteger is ported
// (right now the big numbers get turned into doubles and lose tons of accuracy)
expect(df, U_INT64_MIN, "9223372036854780000");
// TODO: uncomment (and fix up) once BigInteger is ported and DecimalFormat can handle it
// (right now the big numbers get turned into doubles and lose tons of accuracy)
//expect2(df, U_INT64_MAX, Int64ToUnicodeString(-U_INT64_MAX));
//expect2(df, U_INT64_MIN, UnicodeString(Int64ToUnicodeString(U_INT64_MIN), 1));
//expect2(df, U_INT64_MAX / 2, Int64ToUnicodeString(-(U_INT64_MAX / 2)));
//expect2(df, U_INT64_MIN / 2, Int64ToUnicodeString(-(U_INT64_MIN / 2)));
// TODO: uncomment (and fix up) once BigDecimal is ported and DecimalFormat can handle it
//expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
//expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
//expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
//expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
}
#endif /* #if !UCONFIG_NO_FORMATTING */

View File

@ -129,6 +129,8 @@ class NumberFormatTest: public CalendarTimeZoneTest {
/* Port of ICU4J rounding test. */
void TestRounding(void);
void TestNonpositiveMultiplier(void);
private:
static UBool equalValue(const Formattable& a, const Formattable& b);