ICU-13678 Cleaning up multiplier implementation and adding public API.
X-SVN-Rev: 41188
This commit is contained in:
parent
921355c6f0
commit
8ea876aadb
@ -103,13 +103,13 @@ number_decimfmtprops.o number_fluent.o number_formatimpl.o number_grouping.o \
|
||||
number_integerwidth.o number_longnames.o number_modifiers.o number_notation.o \
|
||||
number_padding.o number_patternmodifier.o number_patternstring.o \
|
||||
number_rounding.o number_scientific.o number_stringbuilder.o \
|
||||
number_mapper.o number_multiplier.o number_currencysymbols.o number_skeletons.o number_capi.o \
|
||||
double-conversion.o double-conversion-bignum-dtoa.o double-conversion-bignum.o \
|
||||
double-conversion-cached-powers.o double-conversion-diy-fp.o \
|
||||
double-conversion-fast-dtoa.o double-conversion-strtod.o \
|
||||
numparse_stringsegment.o numparse_unisets.o numparse_parsednumber.o \
|
||||
numparse_impl.o numparse_symbols.o numparse_decimal.o numparse_scientific.o \
|
||||
numparse_currency.o numparse_affixes.o numparse_compositions.o numparse_validators.o \
|
||||
number_mapper.o number_multiplier.o number_currencysymbols.o number_skeletons.o number_capi.o \
|
||||
numparse_stringsegment.o numparse_unisets.o numparse_parsednumber.o numparse_impl.o \
|
||||
numparse_symbols.o numparse_decimal.o numparse_scientific.o numparse_currency.o \
|
||||
numparse_affixes.o numparse_compositions.o numparse_validators.o \
|
||||
|
||||
|
||||
## Header files to install
|
||||
|
@ -198,10 +198,18 @@ void DecimalQuantity::roundToIncrement(double roundingIncrement, RoundingMode ro
|
||||
roundToMagnitude(-maxFrac, roundingMode, status);
|
||||
}
|
||||
|
||||
void DecimalQuantity::multiplyBy(int32_t multiplicand) {
|
||||
void DecimalQuantity::multiplyBy(double multiplicand) {
|
||||
if (isInfinite() || isZero() || isNaN()) {
|
||||
return;
|
||||
}
|
||||
// Cover a few simple cases...
|
||||
if (multiplicand == 1) {
|
||||
return;
|
||||
} else if (multiplicand == -1) {
|
||||
negate();
|
||||
return;
|
||||
}
|
||||
// Do math for all other cases...
|
||||
// TODO: Should we convert to decNumber instead?
|
||||
double temp = toDouble();
|
||||
temp *= multiplicand;
|
||||
|
@ -93,7 +93,7 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory {
|
||||
*
|
||||
* @param multiplicand The value by which to multiply.
|
||||
*/
|
||||
void multiplyBy(int32_t multiplicand);
|
||||
void multiplyBy(double multiplicand);
|
||||
|
||||
/** Flips the sign from positive to negative and back. */
|
||||
void negate();
|
||||
|
@ -233,6 +233,20 @@ Derived NumberFormatterSettings<Derived>::decimal(const UNumberDecimalSeparatorD
|
||||
return move;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
Derived NumberFormatterSettings<Derived>::multiplier(const Multiplier& multiplier) const& {
|
||||
Derived copy(*this);
|
||||
copy.fMacros.multiplier = multiplier;
|
||||
return copy;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
Derived NumberFormatterSettings<Derived>::multiplier(const Multiplier& multiplier)&& {
|
||||
Derived move(std::move(*this));
|
||||
move.fMacros.multiplier = multiplier;
|
||||
return move;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
Derived NumberFormatterSettings<Derived>::padding(const Padder& padder) const& {
|
||||
Derived copy(*this);
|
||||
|
@ -257,11 +257,7 @@ MacroProps NumberPropertyMapper::oldToNew(const DecimalFormatProperties& propert
|
||||
// MULTIPLIERS //
|
||||
/////////////////
|
||||
|
||||
if (properties.magnitudeMultiplier != 0) {
|
||||
macros.multiplier = Multiplier::magnitude(properties.magnitudeMultiplier);
|
||||
} else if (properties.multiplier != 1) {
|
||||
macros.multiplier = Multiplier::integer(properties.multiplier);
|
||||
}
|
||||
macros.multiplier = multiplierFromProperties(properties);
|
||||
|
||||
//////////////////////
|
||||
// PROPERTY EXPORTS //
|
||||
|
@ -11,37 +11,77 @@
|
||||
|
||||
#include "number_types.h"
|
||||
#include "number_multiplier.h"
|
||||
#include "numparse_validators.h"
|
||||
|
||||
using namespace icu;
|
||||
using namespace icu::number;
|
||||
using namespace icu::number::impl;
|
||||
using namespace icu::numparse::impl;
|
||||
|
||||
|
||||
Multiplier::Multiplier(int32_t magnitudeMultiplier, int32_t multiplier)
|
||||
: magnitudeMultiplier(magnitudeMultiplier), multiplier(multiplier) {}
|
||||
Multiplier::Multiplier(int32_t magnitude, double arbitrary)
|
||||
: fMagnitude(magnitude), fArbitrary(arbitrary) {}
|
||||
|
||||
Multiplier Multiplier::magnitude(int32_t magnitudeMultiplier) {
|
||||
return {magnitudeMultiplier, 1};
|
||||
Multiplier Multiplier::none() {
|
||||
return {0, 1};
|
||||
}
|
||||
|
||||
Multiplier Multiplier::integer(int32_t multiplier) {
|
||||
return {0, multiplier};
|
||||
Multiplier Multiplier::powerOfTen(int32_t power) {
|
||||
return {power, 1};
|
||||
}
|
||||
|
||||
|
||||
void MultiplierChain::setAndChain(const Multiplier& multiplier, const MicroPropsGenerator* parent) {
|
||||
this->multiplier = multiplier;
|
||||
this->parent = parent;
|
||||
Multiplier Multiplier::arbitraryDecimal(StringPiece multiplicand) {
|
||||
// TODO: Fix this hack
|
||||
UErrorCode localError = U_ZERO_ERROR;
|
||||
DecimalQuantity dq;
|
||||
dq.setToDecNumber(multiplicand, localError);
|
||||
return {0, dq.toDouble()};
|
||||
}
|
||||
|
||||
void
|
||||
MultiplierChain::processQuantity(DecimalQuantity& quantity, MicroProps& micros, UErrorCode& status) const {
|
||||
parent->processQuantity(quantity, micros, status);
|
||||
quantity.adjustMagnitude(multiplier.magnitudeMultiplier);
|
||||
if (multiplier.multiplier != 1) {
|
||||
quantity.multiplyBy(multiplier.multiplier);
|
||||
Multiplier Multiplier::arbitraryDouble(double multiplicand) {
|
||||
return {0, multiplicand};
|
||||
}
|
||||
|
||||
void Multiplier::applyTo(impl::DecimalQuantity& quantity) const {
|
||||
quantity.adjustMagnitude(fMagnitude);
|
||||
quantity.multiplyBy(fArbitrary);
|
||||
}
|
||||
|
||||
void Multiplier::applyReciprocalTo(impl::DecimalQuantity& quantity) const {
|
||||
quantity.adjustMagnitude(-fMagnitude);
|
||||
if (fArbitrary != 0) {
|
||||
quantity.multiplyBy(1 / fArbitrary);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MultiplierFormatHandler::setAndChain(const Multiplier& multiplier, const MicroPropsGenerator* parent) {
|
||||
this->multiplier = multiplier;
|
||||
this->parent = parent;
|
||||
}
|
||||
|
||||
void MultiplierFormatHandler::processQuantity(DecimalQuantity& quantity, MicroProps& micros,
|
||||
UErrorCode& status) const {
|
||||
parent->processQuantity(quantity, micros, status);
|
||||
multiplier.applyTo(quantity);
|
||||
}
|
||||
|
||||
|
||||
// NOTE: MultiplierParseHandler is declared in the header numparse_validators.h
|
||||
MultiplierParseHandler::MultiplierParseHandler(::icu::number::Multiplier multiplier)
|
||||
: fMultiplier(multiplier) {}
|
||||
|
||||
void MultiplierParseHandler::postProcess(ParsedNumber& result) const {
|
||||
if (!result.quantity.bogus) {
|
||||
fMultiplier.applyReciprocalTo(result.quantity);
|
||||
// NOTE: It is okay if the multiplier was negative.
|
||||
}
|
||||
}
|
||||
|
||||
UnicodeString MultiplierParseHandler::toString() const {
|
||||
return u"<Multiplier>";
|
||||
}
|
||||
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
@ -8,14 +8,18 @@
|
||||
#define __SOURCE_NUMBER_MULTIPLIER_H__
|
||||
|
||||
#include "numparse_types.h"
|
||||
#include "number_decimfmtprops.h"
|
||||
|
||||
U_NAMESPACE_BEGIN namespace number {
|
||||
namespace impl {
|
||||
|
||||
|
||||
class MultiplierChain : public MicroPropsGenerator, public UMemory {
|
||||
/**
|
||||
* Wraps a {@link Multiplier} for use in the number formatting pipeline.
|
||||
*/
|
||||
class MultiplierFormatHandler : public MicroPropsGenerator, public UMemory {
|
||||
public:
|
||||
void setAndChain(const Multiplier& other, const MicroPropsGenerator* parent);
|
||||
void setAndChain(const Multiplier& multiplier, const MicroPropsGenerator* parent);
|
||||
|
||||
void processQuantity(DecimalQuantity& quantity, MicroProps& micros,
|
||||
UErrorCode& status) const U_OVERRIDE;
|
||||
@ -26,6 +30,18 @@ class MultiplierChain : public MicroPropsGenerator, public UMemory {
|
||||
};
|
||||
|
||||
|
||||
/** Gets a Multiplier from a DecimalFormatProperties. In Java, defined in RoundingUtils.java */
|
||||
static inline Multiplier multiplierFromProperties(const DecimalFormatProperties& properties) {
|
||||
if (properties.magnitudeMultiplier != 0) {
|
||||
return Multiplier::powerOfTen(properties.magnitudeMultiplier);
|
||||
} else if (properties.multiplier != 1) {
|
||||
return Multiplier::arbitraryDouble(properties.multiplier);
|
||||
} else {
|
||||
return Multiplier::none();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace impl
|
||||
} // namespace number
|
||||
U_NAMESPACE_END
|
||||
|
@ -75,7 +75,7 @@ struct MicroProps : public MicroPropsGenerator {
|
||||
ScientificModifier scientificModifier;
|
||||
EmptyModifier emptyWeakModifier{false};
|
||||
EmptyModifier emptyStrongModifier{true};
|
||||
MultiplierChain multiplier;
|
||||
MultiplierFormatHandler multiplier;
|
||||
} helpers;
|
||||
|
||||
|
||||
|
@ -180,14 +180,10 @@ NumberParserImpl::createParserFromProperties(const number::impl::DecimalFormatPr
|
||||
properties.decimalSeparatorAlwaysShown || properties.maximumFractionDigits != 0;
|
||||
parser->addMatcher(parser->fLocalValidators.decimalSeparator = {patternHasDecimalSeparator});
|
||||
}
|
||||
|
||||
// TODO: MULTIPLIER
|
||||
// if (properties.getMultiplier() != null) {
|
||||
// // We need to use a math context in order to prevent non-terminating decimal expansions.
|
||||
// // This is only used when dividing by the multiplier.
|
||||
// parser.addMatcher(new MultiplierHandler(properties.getMultiplier(),
|
||||
// RoundingUtils.getMathContextOr34Digits(properties)));
|
||||
// }
|
||||
// NOTE: Don't look at magnitude multiplier here. That is performed when percent sign is seen.
|
||||
if (properties.multiplier != 1) {
|
||||
parser->addMatcher(parser->fLocalValidators.multiplier = {multiplierFromProperties(properties)});
|
||||
}
|
||||
|
||||
parser->freeze();
|
||||
return parser.orphan();
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "number_decimfmtprops.h"
|
||||
#include "unicode/localpointer.h"
|
||||
#include "numparse_validators.h"
|
||||
#include "number_multiplier.h"
|
||||
|
||||
U_NAMESPACE_BEGIN namespace numparse {
|
||||
namespace impl {
|
||||
@ -78,6 +79,7 @@ class NumberParserImpl : public MutableMatcherCollection {
|
||||
RequireDecimalSeparatorValidator decimalSeparator;
|
||||
RequireExponentValidator exponent;
|
||||
RequireNumberValidator number;
|
||||
MultiplierParseHandler multiplier;
|
||||
} fLocalValidators;
|
||||
|
||||
explicit NumberParserImpl(parse_flags_t parseFlags);
|
||||
|
@ -77,6 +77,26 @@ class RequireNumberValidator : public ValidationMatcher, public UMemory {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Wraps a {@link Multiplier} for use in the number parsing pipeline.
|
||||
*
|
||||
* NOTE: Implemented in number_multiplier.cpp
|
||||
*/
|
||||
class MultiplierParseHandler : public ValidationMatcher, public UMemory {
|
||||
public:
|
||||
MultiplierParseHandler() = default; // leaves instance in valid but undefined state
|
||||
|
||||
MultiplierParseHandler(::icu::number::Multiplier multiplier);
|
||||
|
||||
void postProcess(ParsedNumber& result) const U_OVERRIDE;
|
||||
|
||||
UnicodeString toString() const U_OVERRIDE;
|
||||
|
||||
private:
|
||||
::icu::number::Multiplier fMultiplier;
|
||||
};
|
||||
|
||||
|
||||
} // namespace impl
|
||||
} // namespace numparse
|
||||
U_NAMESPACE_END
|
||||
|
@ -86,6 +86,7 @@ namespace impl {
|
||||
|
||||
// Forward declarations:
|
||||
class NumberParserImpl;
|
||||
class MultiplierParseHandler;
|
||||
|
||||
}
|
||||
}
|
||||
@ -142,7 +143,7 @@ class NumberStringBuilder;
|
||||
class AffixPatternProvider;
|
||||
class NumberPropertyMapper;
|
||||
struct DecimalFormatProperties;
|
||||
class MultiplierChain;
|
||||
class MultiplierFormatHandler;
|
||||
class CurrencySymbols;
|
||||
class GeneratorHelpers;
|
||||
|
||||
@ -895,7 +896,6 @@ class U_I18N_API IntegerWidth : public UMemory {
|
||||
* The minimum number of places before the decimal separator.
|
||||
* @return An IntegerWidth for chaining or passing to the NumberFormatter integerWidth() setter.
|
||||
* @draft ICU 60
|
||||
* @see NumberFormatter
|
||||
*/
|
||||
static IntegerWidth zeroFillTo(int32_t minInt);
|
||||
|
||||
@ -909,7 +909,6 @@ class U_I18N_API IntegerWidth : public UMemory {
|
||||
* truncation.
|
||||
* @return An IntegerWidth for passing to the NumberFormatter integerWidth() setter.
|
||||
* @draft ICU 60
|
||||
* @see NumberFormatter
|
||||
*/
|
||||
IntegerWidth truncateAt(int32_t maxInt);
|
||||
|
||||
@ -966,6 +965,94 @@ class U_I18N_API IntegerWidth : public UMemory {
|
||||
friend class impl::GeneratorHelpers;
|
||||
};
|
||||
|
||||
/**
|
||||
* A class that defines a quantity by which a number should be multiplied when formatting.
|
||||
*
|
||||
* <p>
|
||||
* To create a Multiplier, use one of the factory methods.
|
||||
*
|
||||
* @draft ICU 62
|
||||
*/
|
||||
class U_I18N_API Multiplier : public UMemory {
|
||||
public:
|
||||
/**
|
||||
* Do not change the value of numbers when formatting or parsing.
|
||||
*
|
||||
* @return A Multiplier to prevent any multiplication.
|
||||
* @draft ICU 62
|
||||
*/
|
||||
static Multiplier none();
|
||||
|
||||
/**
|
||||
* Multiply numbers by 100 before formatting. Useful for combining with a percent unit:
|
||||
*
|
||||
* <pre>
|
||||
* NumberFormatter::with().unit(NoUnit::percent()).multiplier(Multiplier::powerOfTen(2))
|
||||
* </pre>
|
||||
*
|
||||
* @return A Multiplier for passing to the setter in NumberFormatter.
|
||||
* @draft ICU 62
|
||||
*/
|
||||
static Multiplier powerOfTen(int32_t power);
|
||||
|
||||
/**
|
||||
* Multiply numbers by an arbitrary value before formatting. Useful for unit conversions.
|
||||
*
|
||||
* This method takes a string in a decimal number format with syntax
|
||||
* as defined in the Decimal Arithmetic Specification, available at
|
||||
* http://speleotrove.com/decimal
|
||||
*
|
||||
* Also see the version of this method that takes a double.
|
||||
*
|
||||
* @return A Multiplier for passing to the setter in NumberFormatter.
|
||||
* @draft ICU 62
|
||||
*/
|
||||
static Multiplier arbitraryDecimal(StringPiece multiplicand);
|
||||
|
||||
/**
|
||||
* Multiply numbers by an arbitrary value before formatting. Useful for unit conversions.
|
||||
*
|
||||
* This method takes a double; also see the version of this method that takes an exact decimal.
|
||||
*
|
||||
* @return A Multiplier for passing to the setter in NumberFormatter.
|
||||
* @draft ICU 62
|
||||
*/
|
||||
static Multiplier arbitraryDouble(double multiplicand);
|
||||
|
||||
private:
|
||||
int32_t fMagnitude;
|
||||
double fArbitrary;
|
||||
|
||||
Multiplier(int32_t magnitude, double arbitrary);
|
||||
|
||||
Multiplier() : fMagnitude(0), fArbitrary(1) {}
|
||||
|
||||
bool isValid() const {
|
||||
return fMagnitude != 0 || fArbitrary != 1;
|
||||
}
|
||||
|
||||
void applyTo(impl::DecimalQuantity& quantity) const;
|
||||
|
||||
void applyReciprocalTo(impl::DecimalQuantity& quantity) const;
|
||||
|
||||
// To allow MacroProps/MicroProps to initialize empty instances:
|
||||
friend struct impl::MacroProps;
|
||||
friend struct impl::MicroProps;
|
||||
|
||||
// To allow NumberFormatterImpl to access isBogus() and perform other operations:
|
||||
friend class impl::NumberFormatterImpl;
|
||||
|
||||
// To allow the helper class MultiplierFormatHandler access to private fields:
|
||||
friend class impl::MultiplierFormatHandler;
|
||||
|
||||
// To allow access to the skeleton generation code:
|
||||
friend class impl::GeneratorHelpers;
|
||||
|
||||
// To allow access to parsing code:
|
||||
friend class ::icu::numparse::impl::NumberParserImpl;
|
||||
friend class ::icu::numparse::impl::MultiplierParseHandler;
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
// Do not enclose entire SymbolsWrapper with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
|
||||
@ -1208,41 +1295,6 @@ class U_I18N_API Padder : public UMemory {
|
||||
};
|
||||
|
||||
// Do not enclose entire MacroProps with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
|
||||
/** @internal */
|
||||
class U_I18N_API Multiplier : public UMemory {
|
||||
public:
|
||||
/** @internal */
|
||||
static Multiplier magnitude(int32_t magnitudeMultiplier);
|
||||
|
||||
/** @internal */
|
||||
static Multiplier integer(int32_t multiplier);
|
||||
|
||||
private:
|
||||
int32_t magnitudeMultiplier;
|
||||
int32_t multiplier;
|
||||
|
||||
Multiplier(int32_t magnitudeMultiplier, int32_t multiplier);
|
||||
|
||||
Multiplier() : magnitudeMultiplier(0), multiplier(1) {}
|
||||
|
||||
bool isValid() const {
|
||||
return magnitudeMultiplier != 0 || multiplier != 1;
|
||||
}
|
||||
|
||||
// To allow MacroProps/MicroProps to initialize empty instances:
|
||||
friend struct MacroProps;
|
||||
friend struct MicroProps;
|
||||
|
||||
// To allow NumberFormatterImpl to access isBogus() and perform other operations:
|
||||
friend class impl::NumberFormatterImpl;
|
||||
|
||||
// To allow the helper class MultiplierChain access to private fields:
|
||||
friend class impl::MultiplierChain;
|
||||
|
||||
// To allow access to the skeleton generation code:
|
||||
friend class impl::GeneratorHelpers;
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
struct U_I18N_API MacroProps : public UMemory {
|
||||
/** @internal */
|
||||
@ -1280,8 +1332,10 @@ struct U_I18N_API MacroProps : public UMemory {
|
||||
/** @internal */
|
||||
UNumberDecimalSeparatorDisplay decimal = UNUM_DECIMAL_SEPARATOR_COUNT;
|
||||
|
||||
Multiplier multiplier; // = Multiplier(); (bogus)
|
||||
/** @internal */
|
||||
Multiplier multiplier; // = Multiplier(); (benign value)
|
||||
|
||||
/** @internal */
|
||||
AffixPatternProvider* affixProvider = nullptr; // no ownership
|
||||
|
||||
/** @internal */
|
||||
@ -1835,11 +1889,48 @@ class U_I18N_API NumberFormatterSettings {
|
||||
* @param style
|
||||
* The decimal separator display strategy to use when rendering numbers.
|
||||
* @return The fluent chain.
|
||||
* @see #sign
|
||||
* @see #decimal
|
||||
* @draft ICU 62
|
||||
*/
|
||||
Derived decimal(const UNumberDecimalSeparatorDisplay &style) &&;
|
||||
|
||||
/**
|
||||
* Sets a multiplier to be used to scale the number by an arbitrary amount before formatting. Most
|
||||
* common values:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Multiply by 100: useful for percentages.
|
||||
* <li>Multiply by an arbitrary value: useful for unit conversions.
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* Pass an element from a {@link Multiplier} factory method to this setter. For example:
|
||||
*
|
||||
* <pre>
|
||||
* NumberFormatter::with().multiplier(Multiplier::powerOfTen(2))
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* The default is to not apply any multiplier.
|
||||
*
|
||||
* @param style
|
||||
* The decimal separator display strategy to use when rendering numbers.
|
||||
* @return The fluent chain
|
||||
* @draft ICU 60
|
||||
*/
|
||||
Derived multiplier(const Multiplier &style) const &;
|
||||
|
||||
/**
|
||||
* Overload of multiplier() for use on an rvalue reference.
|
||||
*
|
||||
* @param style
|
||||
* The multiplier separator display strategy to use when rendering numbers.
|
||||
* @return The fluent chain.
|
||||
* @see #multiplier
|
||||
* @draft ICU 62
|
||||
*/
|
||||
Derived multiplier(const Multiplier &style) &&;
|
||||
|
||||
#ifndef U_HIDE_INTERNAL_API
|
||||
|
||||
/**
|
||||
|
@ -64,6 +64,7 @@ class NumberFormatterApiTest : public IntlTest {
|
||||
//void symbolsOverride();
|
||||
void sign();
|
||||
void decimal();
|
||||
void multiplier();
|
||||
void locale();
|
||||
void formatTypes();
|
||||
void errors();
|
||||
|
@ -77,6 +77,7 @@ void NumberFormatterApiTest::runIndexedTest(int32_t index, UBool exec, const cha
|
||||
//TESTCASE_AUTO(symbolsOverride);
|
||||
TESTCASE_AUTO(sign);
|
||||
TESTCASE_AUTO(decimal);
|
||||
TESTCASE_AUTO(multiplier);
|
||||
TESTCASE_AUTO(locale);
|
||||
TESTCASE_AUTO(formatTypes);
|
||||
TESTCASE_AUTO(errors);
|
||||
@ -1909,6 +1910,83 @@ void NumberFormatterApiTest::decimal() {
|
||||
u"0.");
|
||||
}
|
||||
|
||||
void NumberFormatterApiTest::multiplier() {
|
||||
assertFormatDescending(
|
||||
u"Multiplier None",
|
||||
u"",
|
||||
NumberFormatter::with().multiplier(Multiplier::none()),
|
||||
Locale::getEnglish(),
|
||||
u"87,650",
|
||||
u"8,765",
|
||||
u"876.5",
|
||||
u"87.65",
|
||||
u"8.765",
|
||||
u"0.8765",
|
||||
u"0.08765",
|
||||
u"0.008765",
|
||||
u"0");
|
||||
|
||||
assertFormatDescending(
|
||||
u"Multiplier Power of Ten",
|
||||
nullptr,
|
||||
NumberFormatter::with().multiplier(Multiplier::powerOfTen(6)),
|
||||
Locale::getEnglish(),
|
||||
u"87,650,000,000",
|
||||
u"8,765,000,000",
|
||||
u"876,500,000",
|
||||
u"87,650,000",
|
||||
u"8,765,000",
|
||||
u"876,500",
|
||||
u"87,650",
|
||||
u"8,765",
|
||||
u"0");
|
||||
|
||||
assertFormatDescending(
|
||||
u"Multiplier Arbitrary Double",
|
||||
nullptr,
|
||||
NumberFormatter::with().multiplier(Multiplier::arbitraryDouble(5.2)),
|
||||
Locale::getEnglish(),
|
||||
u"455,780",
|
||||
u"45,578",
|
||||
u"4,557.8",
|
||||
u"455.78",
|
||||
u"45.578",
|
||||
u"4.5578",
|
||||
u"0.45578",
|
||||
u"0.045578",
|
||||
u"0");
|
||||
|
||||
assertFormatDescending(
|
||||
u"Multiplier Arbitrary BigDecimal",
|
||||
nullptr,
|
||||
NumberFormatter::with().multiplier(Multiplier::arbitraryDecimal({"5.2", -1})),
|
||||
Locale::getEnglish(),
|
||||
u"455,780",
|
||||
u"45,578",
|
||||
u"4,557.8",
|
||||
u"455.78",
|
||||
u"45.578",
|
||||
u"4.5578",
|
||||
u"0.45578",
|
||||
u"0.045578",
|
||||
u"0");
|
||||
|
||||
assertFormatDescending(
|
||||
u"Multiplier Zero",
|
||||
nullptr,
|
||||
NumberFormatter::with().multiplier(Multiplier::arbitraryDouble(0)),
|
||||
Locale::getEnglish(),
|
||||
u"0",
|
||||
u"0",
|
||||
u"0",
|
||||
u"0",
|
||||
u"0",
|
||||
u"0",
|
||||
u"0",
|
||||
u"0",
|
||||
u"0");
|
||||
}
|
||||
|
||||
void NumberFormatterApiTest::locale() {
|
||||
// Coverage for the locale setters.
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
@ -4,6 +4,7 @@ package com.ibm.icu.impl.number;
|
||||
|
||||
import com.ibm.icu.impl.Utility;
|
||||
import com.ibm.icu.number.IntegerWidth;
|
||||
import com.ibm.icu.number.Multiplier;
|
||||
import com.ibm.icu.number.Notation;
|
||||
import com.ibm.icu.number.NumberFormatter.DecimalSeparatorDisplay;
|
||||
import com.ibm.icu.number.NumberFormatter.SignDisplay;
|
||||
@ -25,8 +26,8 @@ public class MacroProps implements Cloneable {
|
||||
public UnitWidth unitWidth;
|
||||
public SignDisplay sign;
|
||||
public DecimalSeparatorDisplay decimal;
|
||||
public Multiplier multiplier;
|
||||
public AffixPatternProvider affixProvider; // not in API; for JDK compatibility mode only
|
||||
public MultiplierImpl multiplier; // not in API; for JDK compatibility mode only
|
||||
public PluralRules rules; // not in API; could be made public in the future
|
||||
public Long threshold; // not in API; controls internal self-regulation threshold
|
||||
public ULocale loc;
|
||||
|
@ -0,0 +1,25 @@
|
||||
// © 2017 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html#License
|
||||
package com.ibm.icu.impl.number;
|
||||
|
||||
import com.ibm.icu.number.Multiplier;
|
||||
|
||||
/**
|
||||
* Wraps a {@link Multiplier} for use in the number formatting pipeline.
|
||||
*/
|
||||
public class MultiplierFormatHandler implements MicroPropsGenerator {
|
||||
final Multiplier multiplier;
|
||||
final MicroPropsGenerator parent;
|
||||
|
||||
public MultiplierFormatHandler(Multiplier multiplier, MicroPropsGenerator parent) {
|
||||
this.multiplier = multiplier;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MicroProps processQuantity(DecimalQuantity quantity) {
|
||||
MicroProps micros = parent.processQuantity(quantity);
|
||||
multiplier.applyTo(quantity);
|
||||
return micros;
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
// © 2017 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html#License
|
||||
package com.ibm.icu.impl.number;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class MultiplierImpl implements MicroPropsGenerator {
|
||||
final int magnitudeMultiplier;
|
||||
final BigDecimal bigDecimalMultiplier;
|
||||
final MicroPropsGenerator parent;
|
||||
|
||||
public MultiplierImpl(int magnitudeMultiplier) {
|
||||
this.magnitudeMultiplier = magnitudeMultiplier;
|
||||
this.bigDecimalMultiplier = null;
|
||||
parent = null;
|
||||
}
|
||||
|
||||
public MultiplierImpl(BigDecimal bigDecimalMultiplier) {
|
||||
this.magnitudeMultiplier = 0;
|
||||
this.bigDecimalMultiplier = bigDecimalMultiplier;
|
||||
parent = null;
|
||||
}
|
||||
|
||||
private MultiplierImpl(MultiplierImpl base, MicroPropsGenerator parent) {
|
||||
this.magnitudeMultiplier = base.magnitudeMultiplier;
|
||||
this.bigDecimalMultiplier = base.bigDecimalMultiplier;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public MicroPropsGenerator copyAndChain(MicroPropsGenerator parent) {
|
||||
return new MultiplierImpl(this, parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MicroProps processQuantity(DecimalQuantity quantity) {
|
||||
MicroProps micros = parent.processQuantity(quantity);
|
||||
quantity.adjustMagnitude(magnitudeMultiplier);
|
||||
if (bigDecimalMultiplier != null) {
|
||||
quantity.multiplyBy(bigDecimalMultiplier);
|
||||
}
|
||||
return micros;
|
||||
}
|
||||
}
|
@ -6,6 +6,8 @@ import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
import com.ibm.icu.number.Multiplier;
|
||||
|
||||
/** @author sffc */
|
||||
public class RoundingUtils {
|
||||
|
||||
@ -147,6 +149,14 @@ public class RoundingUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/** The default MathContext, unlimited-precision version. */
|
||||
public static final MathContext DEFAULT_MATH_CONTEXT_UNLIMITED
|
||||
= MATH_CONTEXT_BY_ROUNDING_MODE_UNLIMITED[DEFAULT_ROUNDING_MODE.ordinal()];
|
||||
|
||||
/** The default MathContext, 34-digit version. */
|
||||
public static final MathContext DEFAULT_MATH_CONTEXT_34_DIGITS
|
||||
= MATH_CONTEXT_BY_ROUNDING_MODE_34_DIGITS[DEFAULT_ROUNDING_MODE.ordinal()];
|
||||
|
||||
/**
|
||||
* Gets the user-specified math context out of the property bag. If there is none, falls back to a
|
||||
* math context with unlimited precision and the user-specified rounding mode, which defaults to
|
||||
@ -198,4 +208,15 @@ public class RoundingUtils {
|
||||
public static MathContext mathContextUnlimited(RoundingMode roundingMode) {
|
||||
return MATH_CONTEXT_BY_ROUNDING_MODE_UNLIMITED[roundingMode.ordinal()];
|
||||
}
|
||||
|
||||
public static Multiplier multiplierFromProperties(DecimalFormatProperties properties) {
|
||||
MathContext mc = getMathContextOr34Digits(properties);
|
||||
if (properties.getMagnitudeMultiplier() != 0) {
|
||||
return Multiplier.powerOfTen(properties.getMagnitudeMultiplier()).withMathContext(mc);
|
||||
} else if (properties.getMultiplier() != null) {
|
||||
return Multiplier.arbitrary(properties.getMultiplier()).withMathContext(mc);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,39 +0,0 @@
|
||||
// © 2017 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html#License
|
||||
package com.ibm.icu.impl.number.parse;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
|
||||
/**
|
||||
* @author sffc
|
||||
*
|
||||
*/
|
||||
public class MultiplierHandler extends ValidationMatcher {
|
||||
|
||||
private final BigDecimal multiplier;
|
||||
private final MathContext mc;
|
||||
private final boolean isNegative;
|
||||
|
||||
public MultiplierHandler(BigDecimal multiplier, MathContext mc) {
|
||||
this.multiplier = BigDecimal.ONE.divide(multiplier, mc).abs();
|
||||
this.mc = mc;
|
||||
isNegative = multiplier.signum() < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcess(ParsedNumber result) {
|
||||
if (result.quantity != null) {
|
||||
result.quantity.multiplyBy(multiplier);
|
||||
result.quantity.roundToMagnitude(result.quantity.getMagnitude() - mc.getPrecision(), mc);
|
||||
if (isNegative) {
|
||||
result.flags ^= ParsedNumber.FLAG_NEGATIVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<MultiplierHandler " + multiplier + ">";
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
// © 2017 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html#License
|
||||
package com.ibm.icu.impl.number.parse;
|
||||
|
||||
import com.ibm.icu.number.Multiplier;
|
||||
|
||||
/**
|
||||
* Wraps a {@link Multiplier} for use in the number parsing pipeline.
|
||||
*/
|
||||
public class MultiplierParseHandler extends ValidationMatcher {
|
||||
|
||||
private final Multiplier multiplier;
|
||||
|
||||
public MultiplierParseHandler(Multiplier multiplier) {
|
||||
this.multiplier = multiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcess(ParsedNumber result) {
|
||||
if (result.quantity != null) {
|
||||
multiplier.applyReciprocalTo(result.quantity);
|
||||
// NOTE: It is okay if the multiplier was negative.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<MultiplierHandler " + multiplier + ">";
|
||||
}
|
||||
}
|
@ -230,11 +230,10 @@ public class NumberParserImpl {
|
||||
|| properties.getMaximumFractionDigits() != 0;
|
||||
parser.addMatcher(RequireDecimalSeparatorValidator.getInstance(patternHasDecimalSeparator));
|
||||
}
|
||||
// NOTE: Don't look at magnitude multiplier here. That is performed when percent sign is seen.
|
||||
if (properties.getMultiplier() != null) {
|
||||
// We need to use a math context in order to prevent non-terminating decimal expansions.
|
||||
// This is only used when dividing by the multiplier.
|
||||
parser.addMatcher(new MultiplierHandler(properties.getMultiplier(),
|
||||
RoundingUtils.getMathContextOr34Digits(properties)));
|
||||
parser.addMatcher(
|
||||
new MultiplierParseHandler(RoundingUtils.multiplierFromProperties(properties)));
|
||||
}
|
||||
|
||||
parser.freeze();
|
||||
|
171
icu4j/main/classes/core/src/com/ibm/icu/number/Multiplier.java
Normal file
171
icu4j/main/classes/core/src/com/ibm/icu/number/Multiplier.java
Normal file
@ -0,0 +1,171 @@
|
||||
// © 2018 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html#License
|
||||
package com.ibm.icu.number;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
|
||||
import com.ibm.icu.impl.number.DecimalQuantity;
|
||||
import com.ibm.icu.impl.number.RoundingUtils;
|
||||
|
||||
/**
|
||||
* A class that defines a quantity by which a number should be multiplied when formatting.
|
||||
*
|
||||
* <p>
|
||||
* To create a Multiplier, use one of the factory methods.
|
||||
*
|
||||
* @draft ICU 62
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
* @see NumberFormatter
|
||||
*/
|
||||
public class Multiplier {
|
||||
|
||||
private static final Multiplier DEFAULT = new Multiplier(0, null);
|
||||
private static final Multiplier HUNDRED = new Multiplier(2, null);
|
||||
private static final Multiplier THOUSAND = new Multiplier(3, null);
|
||||
|
||||
private static final BigDecimal BIG_DECIMAL_100 = BigDecimal.valueOf(100);
|
||||
private static final BigDecimal BIG_DECIMAL_1000 = BigDecimal.valueOf(1000);
|
||||
|
||||
final int magnitude;
|
||||
final BigDecimal arbitrary;
|
||||
final BigDecimal reciprocal;
|
||||
final MathContext mc;
|
||||
|
||||
private Multiplier(int magnitude, BigDecimal arbitrary) {
|
||||
this(magnitude, arbitrary, RoundingUtils.DEFAULT_MATH_CONTEXT_34_DIGITS);
|
||||
}
|
||||
|
||||
private Multiplier(int magnitude, BigDecimal arbitrary, MathContext mc) {
|
||||
this.magnitude = magnitude;
|
||||
this.arbitrary = arbitrary;
|
||||
this.mc = mc;
|
||||
// We need to use a math context in order to prevent non-terminating decimal expansions.
|
||||
// This is only used when dividing by the multiplier.
|
||||
if (arbitrary != null && BigDecimal.ZERO.compareTo(arbitrary) != 0) {
|
||||
this.reciprocal = BigDecimal.ONE.divide(arbitrary, mc);
|
||||
} else {
|
||||
this.reciprocal = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not change the value of numbers when formatting or parsing.
|
||||
*
|
||||
* @return A Multiplier to prevent any multiplication.
|
||||
* @draft ICU 62
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
* @see NumberFormatter
|
||||
*/
|
||||
public static Multiplier none() {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply numbers by 100 before formatting. Useful for combining with a percent unit:
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* NumberFormatter.with().unit(NoUnit.PERCENT).multiplier(Multiplier.powerOfTen(2))
|
||||
* </pre>
|
||||
*
|
||||
* @return A Multiplier for passing to the setter in NumberFormatter.
|
||||
* @draft ICU 62
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
* @see NumberFormatter
|
||||
*/
|
||||
public static Multiplier powerOfTen(int power) {
|
||||
if (power == 0) {
|
||||
return DEFAULT;
|
||||
} else if (power == 2) {
|
||||
return HUNDRED;
|
||||
} else if (power == 3) {
|
||||
return THOUSAND;
|
||||
} else {
|
||||
return new Multiplier(power, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply numbers by an arbitrary value before formatting. Useful for unit conversions.
|
||||
* <p>
|
||||
* This method takes a BigDecimal; also see the version that takes a double.
|
||||
*
|
||||
* @return A Multiplier for passing to the setter in NumberFormatter.
|
||||
* @draft ICU 62
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
* @see NumberFormatter
|
||||
*/
|
||||
public static Multiplier arbitrary(BigDecimal multiplicand) {
|
||||
if (multiplicand.compareTo(BigDecimal.ONE) == 0) {
|
||||
return DEFAULT;
|
||||
} else if (multiplicand.compareTo(BIG_DECIMAL_100) == 0) {
|
||||
return HUNDRED;
|
||||
} else if (multiplicand.compareTo(BIG_DECIMAL_1000) == 0) {
|
||||
return THOUSAND;
|
||||
} else {
|
||||
return new Multiplier(0, multiplicand);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply numbers by an arbitrary value before formatting. Useful for unit conversions.
|
||||
* <p>
|
||||
* This method takes a double; also see the version that takes a BigDecimal.
|
||||
*
|
||||
* @return A Multiplier for passing to the setter in NumberFormatter.
|
||||
* @draft ICU 62
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
* @see NumberFormatter
|
||||
*/
|
||||
public static Multiplier arbitrary(double multiplicand) {
|
||||
if (multiplicand == 1) {
|
||||
return DEFAULT;
|
||||
} else if (multiplicand == 100.0) {
|
||||
return HUNDRED;
|
||||
} else if (multiplicand == 1000.0) {
|
||||
return THOUSAND;
|
||||
} else {
|
||||
return new Multiplier(0, BigDecimal.valueOf(multiplicand));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated ICU 62 This API is ICU internal only.
|
||||
*/
|
||||
@Deprecated
|
||||
public Multiplier withMathContext(MathContext mc) {
|
||||
// TODO: Make this public?
|
||||
if (this.mc.equals(mc)) {
|
||||
return this;
|
||||
}
|
||||
return new Multiplier(magnitude, arbitrary, mc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated ICU 62 This API is ICU internal only.
|
||||
*/
|
||||
@Deprecated
|
||||
public void applyTo(DecimalQuantity quantity) {
|
||||
quantity.adjustMagnitude(magnitude);
|
||||
if (arbitrary != null) {
|
||||
quantity.multiplyBy(arbitrary);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated ICU 62 This API is ICU internal only.
|
||||
*/
|
||||
@Deprecated
|
||||
public void applyReciprocalTo(DecimalQuantity quantity) {
|
||||
quantity.adjustMagnitude(-magnitude);
|
||||
if (reciprocal != null) {
|
||||
quantity.multiplyBy(reciprocal);
|
||||
quantity.roundToMagnitude(quantity.getMagnitude() - mc.getPrecision(), mc);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -12,6 +12,7 @@ import com.ibm.icu.impl.number.LongNameHandler;
|
||||
import com.ibm.icu.impl.number.MacroProps;
|
||||
import com.ibm.icu.impl.number.MicroProps;
|
||||
import com.ibm.icu.impl.number.MicroPropsGenerator;
|
||||
import com.ibm.icu.impl.number.MultiplierFormatHandler;
|
||||
import com.ibm.icu.impl.number.MutablePatternModifier;
|
||||
import com.ibm.icu.impl.number.NumberStringBuilder;
|
||||
import com.ibm.icu.impl.number.Padder;
|
||||
@ -183,7 +184,7 @@ class NumberFormatterImpl {
|
||||
|
||||
// Multiplier (compatibility mode value).
|
||||
if (macros.multiplier != null) {
|
||||
chain = macros.multiplier.copyAndChain(chain);
|
||||
chain = new MultiplierFormatHandler(macros.multiplier, chain);
|
||||
}
|
||||
|
||||
// Rounding strategy
|
||||
|
@ -39,9 +39,10 @@ public abstract class NumberFormatterSettings<T extends NumberFormatterSettings<
|
||||
static final int KEY_UNIT_WIDTH = 9;
|
||||
static final int KEY_SIGN = 10;
|
||||
static final int KEY_DECIMAL = 11;
|
||||
static final int KEY_THRESHOLD = 12;
|
||||
static final int KEY_PER_UNIT = 13;
|
||||
static final int KEY_MAX = 14;
|
||||
static final int KEY_MULTIPLIER = 12;
|
||||
static final int KEY_THRESHOLD = 13;
|
||||
static final int KEY_PER_UNIT = 14;
|
||||
static final int KEY_MAX = 15;
|
||||
|
||||
final NumberFormatterSettings<?> parent;
|
||||
final int key;
|
||||
@ -441,6 +442,36 @@ public abstract class NumberFormatterSettings<T extends NumberFormatterSettings<
|
||||
return create(KEY_DECIMAL, style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a multiplier to be used to scale the number by an arbitrary amount before formatting. Most
|
||||
* common values:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Multiply by 100: useful for percentages.
|
||||
* <li>Multiply by an arbitrary value: useful for unit conversions.
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* Pass an element from a {@link Multiplier} factory method to this setter. For example:
|
||||
*
|
||||
* <pre>
|
||||
* NumberFormatter.with().multiplier(Multiplier.powerOfTen(2))
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* The default is to not apply any multiplier.
|
||||
*
|
||||
* @param multiplier
|
||||
* An amount to be multiplied against numbers before formatting.
|
||||
* @return The fluent chain
|
||||
* @see Multiplier
|
||||
* @draft ICU 62
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public T multiplier(Multiplier multiplier) {
|
||||
return create(KEY_MULTIPLIER, multiplier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method to set a starting macros.
|
||||
*
|
||||
@ -568,6 +599,11 @@ public abstract class NumberFormatterSettings<T extends NumberFormatterSettings<
|
||||
macros.decimal = (DecimalSeparatorDisplay) current.value;
|
||||
}
|
||||
break;
|
||||
case KEY_MULTIPLIER:
|
||||
if (macros.multiplier == null) {
|
||||
macros.multiplier = (Multiplier) current.value;
|
||||
}
|
||||
break;
|
||||
case KEY_THRESHOLD:
|
||||
if (macros.threshold == null) {
|
||||
macros.threshold = (Long) current.value;
|
||||
|
@ -11,7 +11,6 @@ import com.ibm.icu.impl.number.CustomSymbolCurrency;
|
||||
import com.ibm.icu.impl.number.DecimalFormatProperties;
|
||||
import com.ibm.icu.impl.number.Grouper;
|
||||
import com.ibm.icu.impl.number.MacroProps;
|
||||
import com.ibm.icu.impl.number.MultiplierImpl;
|
||||
import com.ibm.icu.impl.number.Padder;
|
||||
import com.ibm.icu.impl.number.PatternStringParser;
|
||||
import com.ibm.icu.impl.number.PropertiesAffixPatternProvider;
|
||||
@ -299,11 +298,7 @@ final class NumberPropertyMapper {
|
||||
// MULTIPLIERS //
|
||||
/////////////////
|
||||
|
||||
if (properties.getMagnitudeMultiplier() != 0) {
|
||||
macros.multiplier = new MultiplierImpl(properties.getMagnitudeMultiplier());
|
||||
} else if (properties.getMultiplier() != null) {
|
||||
macros.multiplier = new MultiplierImpl(properties.getMultiplier());
|
||||
}
|
||||
macros.multiplier = RoundingUtils.multiplierFromProperties(properties);
|
||||
|
||||
//////////////////////
|
||||
// PROPERTY EXPORTS //
|
||||
|
@ -11,6 +11,7 @@ import com.ibm.icu.impl.PatternProps;
|
||||
import com.ibm.icu.impl.SoftCache;
|
||||
import com.ibm.icu.impl.StringSegment;
|
||||
import com.ibm.icu.impl.number.MacroProps;
|
||||
import com.ibm.icu.impl.number.RoundingUtils;
|
||||
import com.ibm.icu.number.NumberFormatter.DecimalSeparatorDisplay;
|
||||
import com.ibm.icu.number.NumberFormatter.GroupingStrategy;
|
||||
import com.ibm.icu.number.NumberFormatter.SignDisplay;
|
||||
@ -1267,7 +1268,7 @@ class NumberSkeletonImpl {
|
||||
}
|
||||
|
||||
// Generate the options
|
||||
if (macros.rounder.mathContext != Rounder.DEFAULT_MATH_CONTEXT) {
|
||||
if (macros.rounder.mathContext != RoundingUtils.DEFAULT_MATH_CONTEXT_UNLIMITED) {
|
||||
sb.append('/');
|
||||
BlueprintHelpers.generateRoundingModeOption(macros.rounder.mathContext.getRoundingMode(),
|
||||
sb);
|
||||
|
@ -26,11 +26,8 @@ public abstract class Rounder implements Cloneable {
|
||||
|
||||
/* package-private final */ MathContext mathContext;
|
||||
|
||||
/* package-private */ static final MathContext DEFAULT_MATH_CONTEXT = RoundingUtils
|
||||
.mathContextUnlimited(RoundingUtils.DEFAULT_ROUNDING_MODE);
|
||||
|
||||
/* package-private */ Rounder() {
|
||||
mathContext = DEFAULT_MATH_CONTEXT;
|
||||
mathContext = RoundingUtils.DEFAULT_MATH_CONTEXT_UNLIMITED;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,6 +29,7 @@ import com.ibm.icu.number.CompactNotation;
|
||||
import com.ibm.icu.number.FractionRounder;
|
||||
import com.ibm.icu.number.IntegerWidth;
|
||||
import com.ibm.icu.number.LocalizedNumberFormatter;
|
||||
import com.ibm.icu.number.Multiplier;
|
||||
import com.ibm.icu.number.Notation;
|
||||
import com.ibm.icu.number.NumberFormatter;
|
||||
import com.ibm.icu.number.NumberFormatter.DecimalSeparatorDisplay;
|
||||
@ -1882,6 +1883,84 @@ public class NumberFormatterApiTest {
|
||||
"0.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiplier() {
|
||||
assertFormatDescending(
|
||||
"Multiplier None",
|
||||
null,
|
||||
NumberFormatter.with().multiplier(Multiplier.none()),
|
||||
ULocale.ENGLISH,
|
||||
"87,650",
|
||||
"8,765",
|
||||
"876.5",
|
||||
"87.65",
|
||||
"8.765",
|
||||
"0.8765",
|
||||
"0.08765",
|
||||
"0.008765",
|
||||
"0");
|
||||
|
||||
assertFormatDescending(
|
||||
"Multiplier Power of Ten",
|
||||
null,
|
||||
NumberFormatter.with().multiplier(Multiplier.powerOfTen(6)),
|
||||
ULocale.ENGLISH,
|
||||
"87,650,000,000",
|
||||
"8,765,000,000",
|
||||
"876,500,000",
|
||||
"87,650,000",
|
||||
"8,765,000",
|
||||
"876,500",
|
||||
"87,650",
|
||||
"8,765",
|
||||
"0");
|
||||
|
||||
assertFormatDescending(
|
||||
"Multiplier Arbitrary Double",
|
||||
null,
|
||||
NumberFormatter.with().multiplier(Multiplier.arbitrary(5.2)),
|
||||
ULocale.ENGLISH,
|
||||
"455,780",
|
||||
"45,578",
|
||||
"4,557.8",
|
||||
"455.78",
|
||||
"45.578",
|
||||
"4.5578",
|
||||
"0.45578",
|
||||
"0.045578",
|
||||
"0");
|
||||
|
||||
assertFormatDescending(
|
||||
"Multiplier Arbitrary BigDecimal",
|
||||
null,
|
||||
NumberFormatter.with().multiplier(Multiplier.arbitrary(new BigDecimal("5.2"))),
|
||||
ULocale.ENGLISH,
|
||||
"455,780",
|
||||
"45,578",
|
||||
"4,557.8",
|
||||
"455.78",
|
||||
"45.578",
|
||||
"4.5578",
|
||||
"0.45578",
|
||||
"0.045578",
|
||||
"0");
|
||||
|
||||
assertFormatDescending(
|
||||
"Multiplier Zero",
|
||||
null,
|
||||
NumberFormatter.with().multiplier(Multiplier.arbitrary(0)),
|
||||
ULocale.ENGLISH,
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void locale() {
|
||||
// Coverage for the locale setters.
|
||||
|
Loading…
Reference in New Issue
Block a user