ICU-10273 Plural Rules Fixed Decimal, improve handling of NaN and Infinity

X-SVN-Rev: 34225
This commit is contained in:
Andy Heninger 2013-09-06 20:02:42 +00:00
parent bd7fd3318f
commit 4d9fad13ef
4 changed files with 42 additions and 15 deletions

View file

@ -1024,6 +1024,17 @@ DecimalFormat::clone() const
FixedDecimal
DecimalFormat::getFixedDecimal(double number, UErrorCode &status) const {
FixedDecimal result;
if (U_FAILURE(status)) {
return result;
}
if (uprv_isNaN(number) || uprv_isPositiveInfinity(fabs(number))) {
// For NaN and Infinity the state of the formatter is ignored.
result.init(number);
return result;
}
int32_t minFractionDigits = getMinimumFractionDigits();
if (fMultiplier == NULL && fScale == 0 && fRoundingIncrement == 0 && areSignificantDigitsUsed() == FALSE &&

View file

@ -817,10 +817,12 @@ RuleChain::~RuleChain() {
UnicodeString
RuleChain::select(const FixedDecimal &number) const {
for (const RuleChain *rules = this; rules != NULL; rules = rules->fNext) {
if (rules->ruleHeader->isFulfilled(number)) {
return rules->fKeyword;
}
if (!number.isNanOrInfinity) {
for (const RuleChain *rules = this; rules != NULL; rules = rules->fNext) {
if (rules->ruleHeader->isFulfilled(number)) {
return rules->fKeyword;
}
}
}
return UnicodeString(TRUE, PLURAL_KEYWORD_OTHER, 5);
}
@ -1382,6 +1384,11 @@ void FixedDecimal::init(double n) {
void FixedDecimal::init(double n, int32_t v, int64_t f) {
isNegative = n < 0;
source = fabs(n);
isNanOrInfinity = uprv_isNaN(source) || uprv_isPositiveInfinity(source);
if (isNanOrInfinity) {
v = 0;
f = 0;
}
visibleDecimalDigitCount = v;
decimalDigits = f;
intValue = (int64_t)source;
@ -1395,9 +1402,6 @@ void FixedDecimal::init(double n, int32_t v, int64_t f) {
}
decimalDigitsWithoutTrailingZeros = fdwtz;
}
if (uprv_isNaN(n)) {
isNanOrInfinity = TRUE;
}
}
@ -1405,7 +1409,7 @@ void FixedDecimal::init(double n, int32_t v, int64_t f) {
// Note: Do not multiply by 10 each time through loop, rounding cruft can build
// up that makes the check for an integer result fail.
// A single multiply of the original number works more reliably.
static int p10[] = {1, 10, 100, 1000, 10000};
static int32_t p10[] = {1, 10, 100, 1000, 10000};
UBool FixedDecimal::quickInit(double n) {
UBool success = FALSE;
n = fabs(n);

View file

@ -170,13 +170,19 @@ private:
};
/**
* class FixedDecimal serves to communicate the properties
* of a formatted number from a decimal formatter to PluralRules::select()
*
* see DecimalFormat::getFixedDecimal()
* @internal
*/
class U_I18N_API FixedDecimal: public UMemory {
public:
/**
* @param n the number
* @param v The number of visible fraction digits
* @param f The fraction digits.
*
* @param n the number, e.g. 12.345
* @param v The number of visible fraction digits, e.g. 3
* @param f The fraction digits, e.g. 345
*/
FixedDecimal(double n, int32_t v, int64_t f);
FixedDecimal(double n, int32_t);

View file

@ -16,6 +16,7 @@
#include "unicode/localpointer.h"
#include "unicode/parseerr.h"
#include "putilimp.h"
#include "plurrule_impl.h"
#define LENGTHOF(array) ((int32_t)(sizeof(array)/sizeof((array)[0])))
@ -657,9 +658,14 @@ void IntlTestDecimalFormatAPI::TestFixedDecimal() {
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
fd = df->getFixedDecimal(uprv_getInfinity(), status);
ASSERT_SUCCESS(status);
ASSERT_EQUAL(TRUE, fd.isNanOrInfinity);
fd = df->getFixedDecimal(0.0, status);
ASSERT_EQUAL(FALSE, fd.isNanOrInfinity);
fd = df->getFixedDecimal(uprv_getNaN(), status);
ASSERT_EQUAL(TRUE, fd.isNanOrInfinity);
ASSERT_SUCCESS(status);
}
#endif /* #if !UCONFIG_NO_FORMATTING */