mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-13 08:53:20 +00:00
ICU-21270 Update FixedDecimal in Java to support exponent
This commit is contained in:
parent
f773df26fd
commit
47230019c6
2 changed files with 117 additions and 9 deletions
|
@ -562,6 +562,8 @@ public class PluralRules implements Serializable {
|
|||
|
||||
final boolean isNegative;
|
||||
|
||||
final int exponent;
|
||||
|
||||
private final int baseFactor;
|
||||
|
||||
/**
|
||||
|
@ -654,9 +656,10 @@ public class PluralRules implements Serializable {
|
|||
* @param v number of digits to the right of the decimal place. e.g 1.00 = 2 25. = 0
|
||||
* @param f Corresponds to f in the plural rules grammar.
|
||||
* The digits to the right of the decimal place as an integer. e.g 1.10 = 10
|
||||
* @param e Suppressed exponent for scientific and compact notation
|
||||
*/
|
||||
@Deprecated
|
||||
public FixedDecimal(double n, int v, long f) {
|
||||
public FixedDecimal(double n, int v, long f, int e) {
|
||||
isNegative = n < 0;
|
||||
source = isNegative ? -n : n;
|
||||
visibleDecimalDigitCount = v;
|
||||
|
@ -664,6 +667,7 @@ public class PluralRules implements Serializable {
|
|||
integerValue = n > MAX
|
||||
? MAX
|
||||
: (long)n;
|
||||
exponent = e;
|
||||
hasIntegerValue = source == integerValue;
|
||||
// check values. TODO make into unit test.
|
||||
//
|
||||
|
@ -694,6 +698,24 @@ public class PluralRules implements Serializable {
|
|||
baseFactor = (int) Math.pow(10, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal CLDR
|
||||
* @deprecated This API is ICU internal only.
|
||||
*/
|
||||
@Deprecated
|
||||
public FixedDecimal(double n, int v, long f) {
|
||||
this(n, v, f, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal CLDR
|
||||
* @deprecated This API is ICU internal only.
|
||||
*/
|
||||
@Deprecated
|
||||
public static FixedDecimal createWithExponent(double n, int v, int e) {
|
||||
return new FixedDecimal(n,v,getFractionalDigits(n, v), e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal CLDR
|
||||
* @deprecated This API is ICU internal only.
|
||||
|
@ -786,6 +808,29 @@ public class PluralRules implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal CLDR
|
||||
* @deprecated This API is ICU internal only
|
||||
*/
|
||||
@Deprecated
|
||||
private FixedDecimal (FixedDecimal other) {
|
||||
// Ugly, but necessary, because constructors must only call other
|
||||
// constructors in the first line of the body, and
|
||||
// FixedDecimal(String) was refactored to support exponents.
|
||||
this.source = other.source;
|
||||
this.visibleDecimalDigitCount = other.visibleDecimalDigitCount;
|
||||
this.visibleDecimalDigitCountWithoutTrailingZeros =
|
||||
other.visibleDecimalDigitCountWithoutTrailingZeros;
|
||||
this.decimalDigits = other.decimalDigits;
|
||||
this.decimalDigitsWithoutTrailingZeros =
|
||||
other.decimalDigitsWithoutTrailingZeros;
|
||||
this.integerValue = other.integerValue;
|
||||
this.hasIntegerValue = other.hasIntegerValue;
|
||||
this.isNegative = other.isNegative;
|
||||
this.exponent = other.exponent;
|
||||
this.baseFactor = other.baseFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal CLDR
|
||||
* @deprecated This API is ICU internal only.
|
||||
|
@ -793,7 +838,28 @@ public class PluralRules implements Serializable {
|
|||
@Deprecated
|
||||
public FixedDecimal (String n) {
|
||||
// Ugly, but for samples we don't care.
|
||||
this(Double.parseDouble(n), getVisibleFractionCount(n));
|
||||
this(parseDecimalSampleRangeNumString(n));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal CLDR
|
||||
* @deprecated This API is ICU internal only
|
||||
*/
|
||||
@Deprecated
|
||||
private static FixedDecimal parseDecimalSampleRangeNumString(String num) {
|
||||
if (num.contains("e")) {
|
||||
int ePos = num.lastIndexOf('e');
|
||||
int expNumPos = ePos + 1;
|
||||
String exponentStr = num.substring(expNumPos);
|
||||
int exponent = Integer.parseInt(exponentStr);
|
||||
String fractionStr = num.substring(0, ePos);
|
||||
return FixedDecimal.createWithExponent(
|
||||
Double.parseDouble(fractionStr),
|
||||
getVisibleFractionCount(fractionStr),
|
||||
exponent);
|
||||
} else {
|
||||
return new FixedDecimal(Double.parseDouble(num), getVisibleFractionCount(num));
|
||||
}
|
||||
}
|
||||
|
||||
private static int getVisibleFractionCount(String value) {
|
||||
|
@ -822,7 +888,7 @@ public class PluralRules implements Serializable {
|
|||
case t: return decimalDigitsWithoutTrailingZeros;
|
||||
case v: return visibleDecimalDigitCount;
|
||||
case w: return visibleDecimalDigitCountWithoutTrailingZeros;
|
||||
case e: return 0;
|
||||
case e: return exponent;
|
||||
default: return source;
|
||||
}
|
||||
}
|
||||
|
@ -844,6 +910,9 @@ public class PluralRules implements Serializable {
|
|||
@Override
|
||||
@Deprecated
|
||||
public int compareTo(FixedDecimal other) {
|
||||
if (exponent != other.exponent) {
|
||||
return doubleValue() < other.doubleValue() ? -1 : 1;
|
||||
}
|
||||
if (integerValue != other.integerValue) {
|
||||
return integerValue < other.integerValue ? -1 : 1;
|
||||
}
|
||||
|
@ -877,7 +946,8 @@ public class PluralRules implements Serializable {
|
|||
return false;
|
||||
}
|
||||
FixedDecimal other = (FixedDecimal)arg0;
|
||||
return source == other.source && visibleDecimalDigitCount == other.visibleDecimalDigitCount && decimalDigits == other.decimalDigits;
|
||||
return source == other.source && visibleDecimalDigitCount == other.visibleDecimalDigitCount && decimalDigits == other.decimalDigits
|
||||
&& exponent == other.exponent;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -898,7 +968,12 @@ public class PluralRules implements Serializable {
|
|||
@Deprecated
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(Locale.ROOT, "%." + visibleDecimalDigitCount + "f", source);
|
||||
String baseString = String.format(Locale.ROOT, "%." + visibleDecimalDigitCount + "f", source);
|
||||
if (exponent == 0) {
|
||||
return baseString;
|
||||
} else {
|
||||
return baseString + "e" + exponent;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -918,7 +993,7 @@ public class PluralRules implements Serializable {
|
|||
@Override
|
||||
public int intValue() {
|
||||
// TODO Auto-generated method stub
|
||||
return (int)integerValue;
|
||||
return (int) longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -928,7 +1003,11 @@ public class PluralRules implements Serializable {
|
|||
@Deprecated
|
||||
@Override
|
||||
public long longValue() {
|
||||
return integerValue;
|
||||
if (exponent == 0) {
|
||||
return integerValue;
|
||||
} else {
|
||||
return (long) (Math.pow(10, exponent) * integerValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -938,7 +1017,7 @@ public class PluralRules implements Serializable {
|
|||
@Deprecated
|
||||
@Override
|
||||
public float floatValue() {
|
||||
return (float) source;
|
||||
return (float) (source * Math.pow(10, exponent));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -948,7 +1027,7 @@ public class PluralRules implements Serializable {
|
|||
@Deprecated
|
||||
@Override
|
||||
public double doubleValue() {
|
||||
return isNegative ? -source : source;
|
||||
return (isNegative ? -source : source) * Math.pow(10, exponent);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -190,6 +190,35 @@ public class PluralRulesTest extends TestFmwk {
|
|||
checkOldSamples(description, test, "other", SampleType.DECIMAL, 99d, 99.1, 99.2d, 999d);
|
||||
}
|
||||
|
||||
/**
|
||||
* This test is for the support of X.YeZ scientific notation of numbers in
|
||||
* the plural sample string.
|
||||
*/
|
||||
@Test
|
||||
public void testSamplesWithExponent() {
|
||||
String description = "one: i = 0,1 @integer 0, 1, 1e5 @decimal 0.0~1.5, 1.1e5; "
|
||||
+ "many: e = 0 and i != 0 and i % 1000000 = 0 and v = 0 or e != 0..5"
|
||||
+ " @integer 1000000, 2e6, 3e6, 4e6, 5e6, 6e6, 7e6, … @decimal 2.1e6, 3.1e6, 4.1e6, 5.1e6, 6.1e6, 7.1e6, …; "
|
||||
+ "other: @integer 2~17, 100, 1000, 10000, 100000, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, …"
|
||||
+ " @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 2.1e5, 3.1e5, 4.1e5, 5.1e5, 6.1e5, 7.1e5, …"
|
||||
;
|
||||
// Creating the PluralRules object means being able to parse numbers
|
||||
// like 1e5 and 1.1e5
|
||||
PluralRules test = PluralRules.createRules(description);
|
||||
checkNewSamples(description, test, "one", PluralRules.SampleType.INTEGER, "@integer 0, 1, 1e5", true,
|
||||
new FixedDecimal(0));
|
||||
checkNewSamples(description, test, "one", PluralRules.SampleType.DECIMAL, "@decimal 0.0~1.5, 1.1e5", true,
|
||||
new FixedDecimal(0, 1));
|
||||
checkNewSamples(description, test, "many", PluralRules.SampleType.INTEGER, "@integer 1000000, 2e6, 3e6, 4e6, 5e6, 6e6, 7e6, …", false,
|
||||
new FixedDecimal(1000000));
|
||||
checkNewSamples(description, test, "many", PluralRules.SampleType.DECIMAL, "@decimal 2.1e6, 3.1e6, 4.1e6, 5.1e6, 6.1e6, 7.1e6, …", false,
|
||||
FixedDecimal.createWithExponent(2.1, 1, 6));
|
||||
checkNewSamples(description, test, "other", PluralRules.SampleType.INTEGER, "@integer 2~17, 100, 1000, 10000, 100000, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, …", false,
|
||||
new FixedDecimal(2));
|
||||
checkNewSamples(description, test, "other", PluralRules.SampleType.DECIMAL, "@decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 2.1e5, 3.1e5, 4.1e5, 5.1e5, 6.1e5, 7.1e5, …", false,
|
||||
new FixedDecimal(2.0, 1));
|
||||
}
|
||||
|
||||
public void checkOldSamples(String description, PluralRules rules, String keyword, SampleType sampleType,
|
||||
Double... expected) {
|
||||
Collection<Double> oldSamples = rules.getSamples(keyword, sampleType);
|
||||
|
|
Loading…
Add table
Reference in a new issue