return baseFactor;
}
+ static final long MAX = (long)1E18;
+
/**
* @internal
* @deprecated This API is ICU internal only.
source = isNegative ? -n : n;
visibleDecimalDigitCount = v;
decimalDigits = f;
- integerValue = (long)n;
+ integerValue = n > MAX
+ ? MAX
+ : (long)n;
hasIntegerValue = source == integerValue;
// check values. TODO make into unit test.
//
if (v == 0) {
return 0;
} else {
+ if (n < 0) {
+ n = -n;
+ }
int baseFactor = (int) Math.pow(10, v);
long scaled = Math.round(n * baseFactor);
return (int) (scaled % baseFactor);
this(n,0);
}
+ private static final long MAX_INTEGER_PART = 1000000000;
/**
+ * Return a guess as to the number of decimals that would be displayed. This is only a guess; callers should
+ * always supply the decimals explicitly if possible. Currently, it is up to 6 decimals (without trailing zeros).
+ * Returns 0 for infinities and nans.
* @internal
* @deprecated This API is ICU internal only.
+ *
*/
@Deprecated
public static int decimals(double n) {
// Ugly...
- String temp = String.valueOf(n);
- return temp.endsWith(".0") ? 0 : temp.length() - temp.indexOf('.') - 1;
+ if (Double.isInfinite(n) || Double.isNaN(n)) {
+ return 0;
+ }
+ if (n < 0) {
+ n = -n;
+ }
+ if (n < MAX_INTEGER_PART) {
+ long temp = (long)(n * 1000000) % 1000000; // get 6 decimals
+ for (int mask = 10, digits = 6; digits > 0; mask *= 10, --digits) {
+ if ((temp % mask) != 0) {
+ return digits;
+ }
+ }
+ return 0;
+ } else {
+ String buf = String.format(Locale.ENGLISH, "%1.15e", n);
+ int ePos = buf.lastIndexOf('e');
+ String exponentStr = buf.substring(ePos+1);
+ int exponent = Integer.parseInt(exponentStr);
+ int numFractionDigits = ePos - 2 - exponent;
+ if (numFractionDigits < 0) {
+ return 0;
+ }
+ for (int i=ePos-1; numFractionDigits > 0; --i) {
+ if (buf.charAt(i) != '0') {
+ break;
+ }
+ --numFractionDigits;
+ }
+ return numFractionDigits;
+ }
}
/**
@Deprecated
@Override
public double doubleValue() {
- return source;
+ return isNegative ? -source : source;
}
/**
}
public String select(FixedDecimal n) {
+ if (Double.isInfinite(n.source) || Double.isNaN(n.source)) {
+ return KEYWORD_OTHER;
+ }
Rule r = selectRule(n);
- // since we have explict 'other', we don't need this.
- // if (r == null) {
- // return KEYWORD_OTHER;
- // }
return r.getKeyword();
}
*/
public class LocaleMatcher {
- private static boolean DEBUG = false;
+ private static boolean DEBUG = true;
private static final ULocale UNKNOWN_LOCALE = new ULocale("und");
*/
@Deprecated
public LocaleMatcher(LocalePriorityList languagePriorityList, LanguageMatcherData matcherData, double threshold) {
- this.matcherData = matcherData;
+ this.matcherData = matcherData == null ? defaultWritten : matcherData;
for (final ULocale language : languagePriorityList) {
add(language, languagePriorityList.getWeight(language));
}
new PluralRulesTest().run(args);
}
+ public void testOverUnderflow() {
+ logln(String.valueOf(Long.MAX_VALUE + 1d));
+ for (double[] testDouble : new double[][]{
+ {1E18, 0, 0, 1E18}, // check overflow
+ {10000000000000.1d, 1, 1, 10000000000000d},
+ {-0.00001d, 1, 5, 0},
+ {1d, 0, 0, 1},
+ {1.1d, 1, 1, 1},
+ {12345d, 0, 0, 12345},
+ {12345.678912d, 678912, 6, 12345},
+ {12345.6789123d, 678912, 6, 12345}, // we only go out 6 digits
+ {1E18, 0, 0, 1E18}, // check overflow
+ {1E19, 0, 0, 1E18}, // check overflow
+ }) {
+ FixedDecimal fd = new FixedDecimal(testDouble[0]);
+ assertEquals(testDouble[0] + "=doubleValue()", testDouble[0], fd.doubleValue());
+ assertEquals(testDouble[0] + " decimalDigits", (int)testDouble[1], fd.decimalDigits);
+ assertEquals(testDouble[0] + " visibleDecimalDigitCount", (int)testDouble[2], fd.visibleDecimalDigitCount);
+ assertEquals(testDouble[0] + " decimalDigitsWithoutTrailingZeros", (int)testDouble[1], fd.decimalDigitsWithoutTrailingZeros);
+ assertEquals(testDouble[0] + " visibleDecimalDigitCountWithoutTrailingZeros", (int)testDouble[2], fd.visibleDecimalDigitCountWithoutTrailingZeros);
+ assertEquals(testDouble[0] + " integerValue", (long)testDouble[3], fd.integerValue);
+ }
+
+ for (ULocale locale : new ULocale[]{ULocale.ENGLISH, new ULocale("cy"), new ULocale("ar")}) {
+ PluralRules rules = factory.forLocale(locale);
+
+ assertEquals(locale + " NaN", "other", rules.select(Double.NaN));
+ assertEquals(locale + " ∞", "other", rules.select(Double.POSITIVE_INFINITY));
+ assertEquals(locale + " -∞", "other", rules.select(Double.NEGATIVE_INFINITY));
+ }
+ }
+
public void testSyntaxRestrictions() {
Object[][] shouldFail = {
{"a:n in 3..10,13..19"},
{"a: n = 1 .. 3"},
{"a: n != 1 .. 3"},
{"a: n ! = 1 .. 3"},
-
+
// more complicated
{"a:n in 3 .. 10 , 13 .. 19"},
{"a: n not is 1", ParseException.class}, // hacked to fail
{"a: n in 1"},
{"a: n not in 1"},
-
+
// multiples also have special exceptions
// TODO enable the following once there is an update to CLDR
// {"a: n is 1,3", ParseException.class},
nf.setMinimumFractionDigits(minFracDigits);
String expectedFormat = row[2];
String expectedKeyword = row[3];
-
+
UFieldPosition pos = new UFieldPosition();
String formatted = nf.format(1.0, new StringBuffer(), pos).toString();
int countVisibleFractionDigits = pos.getCountVisibleFractionDigits();
}
logln("max \tsize:\t" + max);
}
-
+
public static class FixedDecimalHandler implements SerializableTest.Handler
{
public Object[] getTestObjects()
new LocaleMatcherTest().run(args);
}
+ public void testChinese() {
+ LocaleMatcher matcher = new LocaleMatcher("zh_CN, zh_TW, iw");
+ ULocale taiwanChinese = new ULocale("zh_TW");
+ ULocale chinaChinese = new ULocale("zh_CN");
+// assertEquals("zh_CN, zh_TW, iw;", taiwanChinese, matcher.getBestMatch("zh_Hant_TW"));
+// assertEquals("zh_CN, zh_TW, iw;", taiwanChinese, matcher.getBestMatch("zh_Hant"));
+// assertEquals("zh_CN, zh_TW, iw;", taiwanChinese, matcher.getBestMatch("zh_TW"));
+// assertEquals("zh_CN, zh_TW, iw;", chinaChinese, matcher.getBestMatch("zh_Hans_CN"));
+// assertEquals("zh_CN, zh_TW, iw;", chinaChinese, matcher.getBestMatch("zh_CN"));
+// assertEquals("zh_CN, zh_TW, iw;", chinaChinese, matcher.getBestMatch("zh"));
+
+ assertEquals("zh_CN, zh_TW, iw;", taiwanChinese, matcher.getBestMatch("zh_Hant_HK"));
+ }
+
public void testenGB() {
final LocaleMatcher matcher = new LocaleMatcher("fr, en, en_GB, es_MX, es_419, es");
assertEquals("en_GB", matcher.getBestMatch("en_NZ").toString());
}
public void testFallbacks() {
- final LocaleMatcher matcher = new LocaleMatcher("en, hi");
- if (!logKnownIssue("10705", "Need new data from CLDR for languageMatching")) {
- assertEquals("hi", matcher.getBestMatch("sa").toString());
- }
+ LocalePriorityList lpl = LocalePriorityList.add("en, hi").build();
+ final LocaleMatcher matcher = new LocaleMatcher(lpl, null, 0.09);
+ assertEquals("hi", matcher.getBestMatch("sa").toString());
}
public void testOverrideData() {