ICU-9889 Implement scaling for decimalFormat
X-SVN-Rev: 33138
This commit is contained in:
parent
feddf0fa6b
commit
96f4a704b2
@ -1,6 +1,6 @@
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1997-2012, International Business Machines Corporation and *
|
||||
* Copyright (C) 1997-2013, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
@ -341,6 +341,7 @@ DecimalFormat::init(UErrorCode &status) {
|
||||
fNegSuffixPattern = 0;
|
||||
fCurrencyChoice = 0;
|
||||
fMultiplier = NULL;
|
||||
fScale = 0;
|
||||
fGroupingSize = 0;
|
||||
fGroupingSize2 = 0;
|
||||
fDecimalSeparatorAlwaysShown = FALSE;
|
||||
@ -1057,6 +1058,8 @@ void DecimalFormat::handleChanged() {
|
||||
debug("No format fastpath: fMinSignificantDigits!=1");
|
||||
} else if(fMultiplier!=NULL) {
|
||||
debug("No format fastpath: fMultiplier!=NULL");
|
||||
} else if(fScale!=0) {
|
||||
debug("No format fastpath: fScale!=0");
|
||||
} else if(0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0)) {
|
||||
debug("No format fastpath: 0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0)");
|
||||
} else if(fDecimalSeparatorAlwaysShown) {
|
||||
@ -1368,6 +1371,26 @@ DecimalFormat::_round(const DigitList &number, DigitList &adjustedNum, UBool& is
|
||||
}
|
||||
}
|
||||
|
||||
if (fScale != 0) {
|
||||
DigitList ten;
|
||||
ten.set(10);
|
||||
if (fScale > 0) {
|
||||
for (int32_t i = fScale ; i > 0 ; i--) {
|
||||
adjustedNum.mult(ten, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return adjustedNum;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int32_t i = fScale ; i < 0 ; i++) {
|
||||
adjustedNum.div(ten, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return adjustedNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: sign is important for zero as well as non-zero numbers.
|
||||
* Proper detection of -0.0 is needed to deal with the
|
||||
@ -1997,6 +2020,22 @@ void DecimalFormat::parse(const UnicodeString& text,
|
||||
digits->div(*fMultiplier, ec);
|
||||
}
|
||||
|
||||
if (fScale != 0) {
|
||||
DigitList ten;
|
||||
ten.set(10);
|
||||
if (fScale > 0) {
|
||||
for (int32_t i = fScale; i > 0; i--) {
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
digits->div(ten,ec);
|
||||
}
|
||||
} else {
|
||||
for (int32_t i = fScale; i < 0; i++) {
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
digits->mult(ten,ec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Negative zero special case:
|
||||
// if parsing integerOnly, change to +0, which goes into an int32 in a Formattable.
|
||||
// if not parsing integerOnly, leave as -0, which a double can represent.
|
||||
@ -5505,6 +5544,10 @@ DecimalFormat& DecimalFormat::setAttribute( UNumberFormatAttribute attr,
|
||||
}
|
||||
break;
|
||||
|
||||
case UNUM_SCALE:
|
||||
fScale = newValue;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = U_UNSUPPORTED_ERROR;
|
||||
break;
|
||||
@ -5580,6 +5623,9 @@ int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr,
|
||||
case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS:
|
||||
return fBoolFlags.get(attr);
|
||||
|
||||
case UNUM_SCALE:
|
||||
return fScale;
|
||||
|
||||
default:
|
||||
status = U_UNSUPPORTED_ERROR;
|
||||
break;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
********************************************************************************
|
||||
* Copyright (C) 1997-2012, International Business Machines
|
||||
* Copyright (C) 1997-2013, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
********************************************************************************
|
||||
*
|
||||
@ -17,7 +17,8 @@
|
||||
* 07/10/97 helena Made ParsePosition a class and get rid of the function
|
||||
* hiding problems.
|
||||
* 09/09/97 aliu Ported over support for exponential formats.
|
||||
* 07/20/98 stephen Changed documentation
|
||||
* 07/20/98 stephen Changed documentation
|
||||
* 01/30/13 emmons Added Scaling methods
|
||||
********************************************************************************
|
||||
*/
|
||||
|
||||
@ -2234,6 +2235,7 @@ private:
|
||||
ChoiceFormat* fCurrencyChoice;
|
||||
|
||||
DigitList * fMultiplier; // NULL for multiplier of one
|
||||
int32_t fScale;
|
||||
int32_t fGroupingSize;
|
||||
int32_t fGroupingSize2;
|
||||
UBool fDecimalSeparatorAlwaysShown;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1997-2012, International Business Machines Corporation and others.
|
||||
* Copyright (C) 1997-2013, International Business Machines Corporation and others.
|
||||
* All Rights Reserved.
|
||||
* Modification History:
|
||||
*
|
||||
@ -795,7 +795,16 @@ typedef enum UNumberFormatAttribute {
|
||||
*/
|
||||
UNUM_PARSE_ALL_INPUT,
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Scale, which adjusts the position of the
|
||||
* decimal point when formatting. Amounts will be multiplied by 10 ^ (scale)
|
||||
* before they are formatted. The default value for the scale is 0 ( no adjustment ).
|
||||
*
|
||||
* <p>Example: setting the scale to 3, 123 formats as "123,000"
|
||||
* <p>Example: setting the scale to -4, 123 formats as "0.0123"
|
||||
*
|
||||
* @draft ICU 51 */
|
||||
UNUM_SCALE,
|
||||
/** Count of "regular" numeric attributes.
|
||||
* @internal */
|
||||
UNUM_NUMERIC_ATTRIBUTE_COUNT,
|
||||
@ -831,7 +840,8 @@ typedef enum UNumberFormatAttribute {
|
||||
* @param attr The attribute to query; one of UNUM_PARSE_INT_ONLY, UNUM_GROUPING_USED,
|
||||
* UNUM_DECIMAL_ALWAYS_SHOWN, UNUM_MAX_INTEGER_DIGITS, UNUM_MIN_INTEGER_DIGITS, UNUM_INTEGER_DIGITS,
|
||||
* UNUM_MAX_FRACTION_DIGITS, UNUM_MIN_FRACTION_DIGITS, UNUM_FRACTION_DIGITS, UNUM_MULTIPLIER,
|
||||
* UNUM_GROUPING_SIZE, UNUM_ROUNDING_MODE, UNUM_FORMAT_WIDTH, UNUM_PADDING_POSITION, UNUM_SECONDARY_GROUPING_SIZE.
|
||||
* UNUM_GROUPING_SIZE, UNUM_ROUNDING_MODE, UNUM_FORMAT_WIDTH, UNUM_PADDING_POSITION, UNUM_SECONDARY_GROUPING_SIZE,
|
||||
* UNUM_SCALE.
|
||||
* @return The value of attr.
|
||||
* @see unum_setAttribute
|
||||
* @see unum_getDoubleAttribute
|
||||
@ -854,7 +864,7 @@ unum_getAttribute(const UNumberFormat* fmt,
|
||||
* UNUM_DECIMAL_ALWAYS_SHOWN, UNUM_MAX_INTEGER_DIGITS, UNUM_MIN_INTEGER_DIGITS, UNUM_INTEGER_DIGITS,
|
||||
* UNUM_MAX_FRACTION_DIGITS, UNUM_MIN_FRACTION_DIGITS, UNUM_FRACTION_DIGITS, UNUM_MULTIPLIER,
|
||||
* UNUM_GROUPING_SIZE, UNUM_ROUNDING_MODE, UNUM_FORMAT_WIDTH, UNUM_PADDING_POSITION, UNUM_SECONDARY_GROUPING_SIZE,
|
||||
* or UNUM_LENIENT_PARSE.
|
||||
* UNUM_LENIENT_PARSE, or UNUM_SCALE.
|
||||
* @param newValue The new value of attr.
|
||||
* @see unum_getAttribute
|
||||
* @see unum_getDoubleAttribute
|
||||
|
@ -1,6 +1,6 @@
|
||||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2010, International Business Machines Corporation and
|
||||
* Copyright (c) 1997-2013, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
@ -54,6 +54,12 @@ void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index, UBool exec, const
|
||||
TestCurrencyPluralInfo();
|
||||
}
|
||||
break;
|
||||
case 4: name = "TestScale";
|
||||
if(exec) {
|
||||
logln((UnicodeString)"Scale test---");
|
||||
TestScale();
|
||||
}
|
||||
break;
|
||||
default: name = ""; break;
|
||||
}
|
||||
}
|
||||
@ -448,14 +454,14 @@ void IntlTestDecimalFormatAPI::testRounding(/*char *par*/)
|
||||
//for +2.55 with RoundingIncrement=1.0
|
||||
pat.setRoundingIncrement(1.0);
|
||||
pat.format(Roundingnumber, resultStr);
|
||||
message= (UnicodeString)"round(" + (double)Roundingnumber + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
|
||||
message= (UnicodeString)"Round() failed: round(" + (double)Roundingnumber + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
|
||||
verify(message, resultStr, result[i++]);
|
||||
message.remove();
|
||||
resultStr.remove();
|
||||
|
||||
//for -2.55 with RoundingIncrement=1.0
|
||||
pat.format(Roundingnumber1, resultStr);
|
||||
message= (UnicodeString)"round(" + (double)Roundingnumber1 + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
|
||||
message= (UnicodeString)"Round() failed: round(" + (double)Roundingnumber1 + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
|
||||
verify(message, resultStr, result[i++]);
|
||||
message.remove();
|
||||
resultStr.remove();
|
||||
@ -467,7 +473,14 @@ void IntlTestDecimalFormatAPI::verify(const UnicodeString& message, const Unicod
|
||||
UnicodeString expectedStr("");
|
||||
expectedStr=expectedStr + expected;
|
||||
if(got != expectedStr ) {
|
||||
errln((UnicodeString)"ERROR: Round() failed: " + message + got + (UnicodeString)" Expected : " + expectedStr);
|
||||
errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)" Expected : " + expectedStr);
|
||||
}
|
||||
}
|
||||
|
||||
void IntlTestDecimalFormatAPI::verifyString(const UnicodeString& message, const UnicodeString& got, UnicodeString& expected){
|
||||
logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected);
|
||||
if(got != expected ) {
|
||||
errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)" Expected : " + expected);
|
||||
}
|
||||
}
|
||||
|
||||
@ -501,4 +514,49 @@ void IntlTestDecimalFormatAPI::testRoundingInc(/*char *par*/)
|
||||
}
|
||||
}
|
||||
|
||||
void IntlTestDecimalFormatAPI::TestScale()
|
||||
{
|
||||
typedef struct TestData {
|
||||
double inputValue;
|
||||
int inputScale;
|
||||
char *expectedOutput;
|
||||
} TestData;
|
||||
|
||||
static TestData testData[] = {
|
||||
{ 100.0, 3, "100,000" },
|
||||
{ 10034.0, -2, "100.34" },
|
||||
{ 0.86, -3, "0.0009" },
|
||||
{ -0.000455, 1, "-0%" },
|
||||
{ -0.000555, 1, "-1%" },
|
||||
{ 0.000455, 1, "0%" },
|
||||
{ 0.000555, 1, "1%" },
|
||||
};
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
DecimalFormat pat(status);
|
||||
if(U_FAILURE(status)) {
|
||||
errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status));
|
||||
return;
|
||||
}
|
||||
|
||||
UnicodeString message;
|
||||
UnicodeString resultStr;
|
||||
UnicodeString exp;
|
||||
UnicodeString percentPattern("#,##0%");
|
||||
pat.setMaximumFractionDigits(4);
|
||||
|
||||
for(int32_t i=0;i < sizeof(testData)/sizeof(testData[0]);i++) {
|
||||
if ( i > 2 ) {
|
||||
pat.applyPattern(percentPattern,status);
|
||||
}
|
||||
pat.setAttribute(UNUM_SCALE,testData[i].inputScale,status);
|
||||
pat.format(testData[i].inputValue, resultStr);
|
||||
message = UnicodeString("Unexpected output for ") + testData[i].inputValue + UnicodeString(" and scale ") + testData[i].inputScale + UnicodeString(". Got: ");
|
||||
exp = testData[i].expectedOutput;
|
||||
verifyString(message, resultStr, exp);
|
||||
message.remove();
|
||||
resultStr.remove();
|
||||
exp.remove();
|
||||
}
|
||||
}
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2009, International Business Machines Corporation and
|
||||
* Copyright (c) 1997-2013, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
@ -27,9 +27,11 @@ public:
|
||||
void testRounding(/*char *par*/);
|
||||
void testRoundingInc(/*char *par*/);
|
||||
void TestCurrencyPluralInfo();
|
||||
void TestScale();
|
||||
private:
|
||||
/*Helper functions */
|
||||
void verify(const UnicodeString& message, const UnicodeString& got, double expected);
|
||||
void verifyString(const UnicodeString& message, const UnicodeString& got, UnicodeString& expected);
|
||||
};
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
Loading…
Reference in New Issue
Block a user