ICU-10273 Plural Rules, add DecimalFormat::getFixedDecimal(). Work in progress.
X-SVN-Rev: 34176
This commit is contained in:
parent
df276b7a30
commit
003c35c1d9
@ -1020,6 +1020,25 @@ DecimalFormat::clone() const
|
||||
return new DecimalFormat(*this);
|
||||
}
|
||||
|
||||
|
||||
FixedDecimal
|
||||
DecimalFormat::getFixedDecimal(double number, UErrorCode &status) {
|
||||
DigitList digits;
|
||||
digits.set(number);
|
||||
UBool isNegative;
|
||||
_round(digits, digits, isNegative, status);
|
||||
double roundedNum = digits.getDouble();
|
||||
FixedDecimal result(roundedNum);
|
||||
int32_t numTrailingFractionZeros = this->getMinimumFractionDigits() - result.visibleDecimalDigitCount;
|
||||
if (numTrailingFractionZeros > 0) {
|
||||
double scaleFactor = pow(10.0, numTrailingFractionZeros);
|
||||
result.decimalDigits *= scaleFactor;
|
||||
result.visibleDecimalDigitCount += numTrailingFractionZeros;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
UnicodeString&
|
||||
@ -1389,6 +1408,10 @@ DecimalFormat::_round(const DigitList &number, DigitList &adjustedNum, UBool& is
|
||||
if (U_FAILURE(status)) {
|
||||
return adjustedNum;
|
||||
}
|
||||
|
||||
// note: number and adjustedNum may refer to the same DigitList, in cases where a copy
|
||||
// is not needed by the caller.
|
||||
|
||||
adjustedNum = number;
|
||||
isNegative = false;
|
||||
if (number.isNaN()) {
|
||||
|
@ -458,6 +458,10 @@ ArgExtractor::number(void) const {
|
||||
return num;
|
||||
}
|
||||
|
||||
// TODO: Thread safety problem? the function of ArgExtractor appears to be to temporarily
|
||||
// setCurrency() on the number formatter, then restore it after the format() is complete.
|
||||
// Another thread could be using the formatter.
|
||||
|
||||
ArgExtractor::ArgExtractor(const NumberFormat& nf, const Formattable& obj, UErrorCode& status)
|
||||
: ncnf((NumberFormat*) &nf), num(&obj), setCurr(FALSE) {
|
||||
|
||||
|
@ -1357,6 +1357,18 @@ FixedDecimal::FixedDecimal(const UnicodeString &num, UErrorCode &status) {
|
||||
}
|
||||
|
||||
|
||||
FixedDecimal::FixedDecimal(const FixedDecimal &other) {
|
||||
source = other.source;
|
||||
visibleDecimalDigitCount = other.visibleDecimalDigitCount;
|
||||
decimalDigits = other.decimalDigits;
|
||||
decimalDigitsWithoutTrailingZeros = other.decimalDigitsWithoutTrailingZeros;
|
||||
intValue = other.intValue;
|
||||
hasIntegerValue = other.hasIntegerValue;
|
||||
isNegative = other.isNegative;
|
||||
isNanOrInfinity = other.isNanOrInfinity;
|
||||
}
|
||||
|
||||
|
||||
void FixedDecimal::init(double n, int32_t v, int64_t f) {
|
||||
isNegative = n < 0;
|
||||
source = fabs(n);
|
||||
@ -1373,6 +1385,9 @@ void FixedDecimal::init(double n, int32_t v, int64_t f) {
|
||||
}
|
||||
decimalDigitsWithoutTrailingZeros = fdwtz;
|
||||
}
|
||||
if (uprv_isNaN(n)) {
|
||||
isNanOrInfinity = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t FixedDecimal::decimals(double n) {
|
||||
|
@ -29,6 +29,9 @@ class PluralRulesTest;
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class AndConstraint;
|
||||
class RuleChain;
|
||||
|
||||
static const UChar DOT = ((UChar)0x002E);
|
||||
static const UChar SINGLE_QUOTE = ((UChar)0x0027);
|
||||
static const UChar SLASH = ((UChar)0x002F);
|
||||
@ -179,6 +182,7 @@ class U_I18N_API FixedDecimal: public UMemory {
|
||||
FixedDecimal(double n, int32_t);
|
||||
explicit FixedDecimal(double n);
|
||||
FixedDecimal(const UnicodeString &s, UErrorCode &ec);
|
||||
FixedDecimal(const FixedDecimal &other);
|
||||
|
||||
double get(tokenType operand) const;
|
||||
int32_t getVisibleFractionDigitCount() const;
|
||||
@ -194,6 +198,7 @@ class U_I18N_API FixedDecimal: public UMemory {
|
||||
int64_t intValue;
|
||||
UBool hasIntegerValue;
|
||||
UBool isNegative;
|
||||
UBool isNanOrInfinity;
|
||||
};
|
||||
|
||||
class AndConstraint : public UMemory {
|
||||
|
@ -60,6 +60,7 @@ class Hashtable;
|
||||
class UnicodeSet;
|
||||
class FieldPositionHandler;
|
||||
class DecimalFormatStaticSets;
|
||||
class FixedDecimal;
|
||||
|
||||
// explicit template instantiation. see digitlst.h
|
||||
#if defined (_MSC_VER)
|
||||
@ -1852,6 +1853,14 @@ public:
|
||||
*/
|
||||
static const char fgNumberPatterns[];
|
||||
|
||||
/**
|
||||
* Get a FixedDecimal corresponding to a double as it would be
|
||||
* formatted by this DecimalFormat.
|
||||
* Internal, not intended for public use.
|
||||
* @internal
|
||||
*/
|
||||
FixedDecimal getFixedDecimal(double number, UErrorCode &status);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
|
@ -10,10 +10,13 @@
|
||||
|
||||
#include "dcfmapts.h"
|
||||
|
||||
#include "unicode/decimfmt.h"
|
||||
#include "unicode/dcfmtsym.h"
|
||||
#include "unicode/parseerr.h"
|
||||
#include "unicode/currpinf.h"
|
||||
#include "unicode/dcfmtsym.h"
|
||||
#include "unicode/decimfmt.h"
|
||||
#include "unicode/localpointer.h"
|
||||
#include "unicode/parseerr.h"
|
||||
|
||||
#include "plurrule_impl.h"
|
||||
|
||||
#define LENGTHOF(array) ((int32_t)(sizeof(array)/sizeof((array)[0])))
|
||||
|
||||
@ -62,7 +65,13 @@ void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index, UBool exec, const
|
||||
TestScale();
|
||||
}
|
||||
break;
|
||||
default: name = ""; break;
|
||||
case 5: name = "TestFixedDecimal";
|
||||
if(exec) {
|
||||
logln((UnicodeString)"TestFixedDecimal ---");
|
||||
TestFixedDecimal();
|
||||
}
|
||||
break;
|
||||
default: name = ""; break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -553,7 +562,8 @@ void IntlTestDecimalFormatAPI::TestScale()
|
||||
}
|
||||
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: ");
|
||||
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();
|
||||
@ -561,4 +571,69 @@ void IntlTestDecimalFormatAPI::TestScale()
|
||||
exp.remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \
|
||||
errln("file %s, line %d: Error status is %s", __FILE__, __LINE__, u_errorName(status)); \
|
||||
status = U_ZERO_ERROR; }}
|
||||
|
||||
#define ASSERT_EQUAL(expect, actual) {if ((expect) != (actual)) { \
|
||||
errln("file %s, line %d: Expected %g, got %g", __FILE__, __LINE__, (double)(expect), (double)(actual)); }}
|
||||
|
||||
|
||||
void IntlTestDecimalFormatAPI::TestFixedDecimal() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
LocalPointer<DecimalFormat> df(new DecimalFormat("###", status));
|
||||
ASSERT_SUCCESS(status);
|
||||
FixedDecimal fd = df->getFixedDecimal(44, status);
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUAL(44, fd.source);
|
||||
ASSERT_EQUAL(0, fd.visibleDecimalDigitCount);
|
||||
|
||||
df.adoptInstead(new DecimalFormat("###.00##", status));
|
||||
ASSERT_SUCCESS(status);
|
||||
fd = df->getFixedDecimal(123.456, status);
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUAL(3, fd.visibleDecimalDigitCount);
|
||||
ASSERT_EQUAL(456, fd.decimalDigits);
|
||||
ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros);
|
||||
ASSERT_EQUAL(123, fd.intValue);
|
||||
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
|
||||
ASSERT_EQUAL(FALSE, fd.isNegative);
|
||||
|
||||
df.adoptInstead(new DecimalFormat("###", status));
|
||||
ASSERT_SUCCESS(status);
|
||||
fd = df->getFixedDecimal(123.456, status);
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUAL(0, fd.visibleDecimalDigitCount);
|
||||
ASSERT_EQUAL(0, fd.decimalDigits);
|
||||
ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
|
||||
ASSERT_EQUAL(123, fd.intValue);
|
||||
ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
|
||||
ASSERT_EQUAL(FALSE, fd.isNegative);
|
||||
|
||||
df.adoptInstead(new DecimalFormat("###.0", status));
|
||||
ASSERT_SUCCESS(status);
|
||||
fd = df->getFixedDecimal(123.01, status);
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUAL(1, fd.visibleDecimalDigitCount);
|
||||
ASSERT_EQUAL(0, fd.decimalDigits);
|
||||
ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
|
||||
ASSERT_EQUAL(123, fd.intValue);
|
||||
ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
|
||||
ASSERT_EQUAL(FALSE, fd.isNegative);
|
||||
|
||||
df.adoptInstead(new DecimalFormat("###.0", status));
|
||||
ASSERT_SUCCESS(status);
|
||||
fd = df->getFixedDecimal(123.06, status);
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUAL(1, fd.visibleDecimalDigitCount);
|
||||
ASSERT_EQUAL(1, fd.decimalDigits);
|
||||
ASSERT_EQUAL(1, fd.decimalDigitsWithoutTrailingZeros);
|
||||
ASSERT_EQUAL(123, fd.intValue);
|
||||
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
|
||||
ASSERT_EQUAL(FALSE, fd.isNegative);
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
@ -28,6 +28,7 @@ public:
|
||||
void testRoundingInc(/*char *par*/);
|
||||
void TestCurrencyPluralInfo();
|
||||
void TestScale();
|
||||
void TestFixedDecimal();
|
||||
private:
|
||||
/*Helper functions */
|
||||
void verify(const UnicodeString& message, const UnicodeString& got, double expected);
|
||||
|
Loading…
Reference in New Issue
Block a user