0001: //##header
0002: /*
0003: *******************************************************************************
0004: * Copyright (C) 1996-2005, International Business Machines Corporation and *
0005: * others. All Rights Reserved. *
0006: *******************************************************************************
0007: */
0008: package com.ibm.icu.dev.test.format;
0009:
0010: import com.ibm.icu.text.RuleBasedNumberFormat;
0011: import com.ibm.icu.dev.test.TestFmwk;
0012: import com.ibm.icu.util.ULocale;
0013:
0014: import java.math.BigInteger;
0015: import java.math.BigDecimal;
0016: import java.util.Locale;
0017: import java.util.Random;
0018: import java.text.DecimalFormat;
0019: import java.text.NumberFormat;
0020:
0021: public class RbnfTest extends TestFmwk {
0022: /**
0023: * Puts a copyright in the .class file
0024: */
0025: private static final String copyrightNotice = "Copyright \u00a91997-1999 IBM Corp. All rights reserved.";
0026:
0027: public static void main(String[] args) {
0028: RbnfTest test = new RbnfTest();
0029:
0030: try {
0031: test.run(args);
0032: } catch (Throwable e) {
0033: System.out
0034: .println("Entire test failed because of exception: "
0035: + e.toString());
0036: e.printStackTrace();
0037: }
0038: }
0039:
0040: static String fracRules = "%main:\n"
0041: +
0042: // this rule formats the number if it's 1 or more. It formats
0043: // the integral part using a DecimalFormat ("#,##0" puts
0044: // thousands separators in the right places) and the fractional
0045: // part using %%frac. If there is no fractional part, it
0046: // just shows the integral part.
0047: " x.0: <#,##0<[ >%%frac>];\n"
0048: +
0049: // this rule formats the number if it's between 0 and 1. It
0050: // shows only the fractional part (0.5 shows up as "1/2," not
0051: // "0 1/2")
0052: " 0.x: >%%frac>;\n"
0053: +
0054: // the fraction rule set. This works the same way as the one in the
0055: // preceding example: We multiply the fractional part of the number
0056: // being formatted by each rule's base value and use the rule that
0057: // produces the result closest to 0 (or the first rule that produces 0).
0058: // Since we only provide rules for the numbers from 2 to 10, we know
0059: // we'll get a fraction with a denominator between 2 and 10.
0060: // "<0<" causes the numerator of the fraction to be formatted
0061: // using numerals
0062: "%%frac:\n" + " 2: 1/2;\n" + " 3: <0</3;\n"
0063: + " 4: <0</4;\n" + " 5: <0</5;\n" + " 6: <0</6;\n"
0064: + " 7: <0</7;\n" + " 8: <0</8;\n" + " 9: <0</9;\n"
0065: + " 10: <0</10;\n";
0066:
0067: static {
0068: // mondo hack
0069: char[] fracRulesArr = fracRules.toCharArray();
0070: int len = fracRulesArr.length;
0071: int change = 2;
0072: for (int i = 0; i < len; ++i) {
0073: char ch = fracRulesArr[i];
0074: if (ch == '\n') {
0075: change = 2; // change ok
0076: } else if (ch == ':') {
0077: change = 1; // change, but once we hit a non-space char, don't change
0078: } else if (ch == ' ') {
0079: if (change != 0) {
0080: fracRulesArr[i] = (char) 0x200e;
0081: }
0082: } else {
0083: if (change == 1) {
0084: change = 0;
0085: }
0086: }
0087: }
0088: fracRules = new String(fracRulesArr);
0089: }
0090:
0091: static final String durationInSecondsRules =
0092: // main rule set for formatting with words
0093: "%with-words:\n"
0094: // take care of singular and plural forms of "second"
0095: + " 0 seconds; 1 second; =0= seconds;\n"
0096: // use %%min to format values greater than 60 seconds
0097: + " 60/60: <%%min<[, >>];\n"
0098: // use %%hr to format values greater than 3,600 seconds
0099: // (the ">>>" below causes us to see the number of minutes
0100: // when when there are zero minutes)
0101: + " 3600/60: <%%hr<[, >>>];\n"
0102: // this rule set takes care of the singular and plural forms
0103: // of "minute"
0104: + "%%min:\n"
0105: + " 0 minutes; 1 minute; =0= minutes;\n"
0106: // this rule set takes care of the singular and plural forms
0107: // of "hour"
0108: + "%%hr:\n"
0109: + " 0 hours; 1 hour; =0= hours;\n"
0110:
0111: // main rule set for formatting in numerals
0112: + "%in-numerals:\n"
0113: // values below 60 seconds are shown with "sec."
0114: + " =0= sec.;\n"
0115: // higher values are shown with colons: %%min-sec is used for
0116: // values below 3,600 seconds...
0117: + " 60: =%%min-sec=;\n"
0118: // ...and %%hr-min-sec is used for values of 3,600 seconds
0119: // and above
0120: + " 3600: =%%hr-min-sec=;\n"
0121: // this rule causes values of less than 10 minutes to show without
0122: // a leading zero
0123: + "%%min-sec:\n"
0124: + " 0: :=00=;\n"
0125: + " 60/60: <0<>>;\n"
0126: // this rule set is used for values of 3,600 or more. Minutes are always
0127: // shown, and always shown with two digits
0128: + "%%hr-min-sec:\n" + " 0: :=00=;\n"
0129: + " 60/60: <00<>>;\n" + " 3600/60: <#,##0<:>>>;\n"
0130: // the lenient-parse rules allow several different characters to be used
0131: // as delimiters between hours, minutes, and seconds
0132: + "%%lenient-parse:\n" + " & : = . = ' ' = -;\n";
0133:
0134: public void TestCoverage() {
0135: // extra calls to boost coverage numbers
0136: RuleBasedNumberFormat fmt0 = new RuleBasedNumberFormat(
0137: RuleBasedNumberFormat.SPELLOUT);
0138: RuleBasedNumberFormat fmt1 = (RuleBasedNumberFormat) fmt0
0139: .clone();
0140: RuleBasedNumberFormat fmt2 = new RuleBasedNumberFormat(
0141: RuleBasedNumberFormat.SPELLOUT);
0142: if (!fmt0.equals(fmt0)) {
0143: errln("self equality fails");
0144: }
0145: if (!fmt0.equals(fmt1)) {
0146: errln("clone equality fails");
0147: }
0148: if (!fmt0.equals(fmt2)) {
0149: errln("duplicate equality fails");
0150: }
0151: String str = fmt0.toString();
0152: logln(str);
0153:
0154: RuleBasedNumberFormat fmt3 = new RuleBasedNumberFormat(
0155: durationInSecondsRules);
0156:
0157: if (fmt0.equals(fmt3)) {
0158: errln("nonequal fails");
0159: }
0160: if (!fmt3.equals(fmt3)) {
0161: errln("self equal 2 fails");
0162: }
0163: str = fmt3.toString();
0164: logln(str);
0165:
0166: String[] names = fmt3.getRuleSetNames();
0167:
0168: try {
0169: fmt3.setDefaultRuleSet(null);
0170: fmt3.setDefaultRuleSet("%%foo");
0171: errln("sdrf %%foo didn't fail");
0172: } catch (Exception e) {
0173: logln("Got the expected exception");
0174: }
0175:
0176: try {
0177: fmt3.setDefaultRuleSet("%bogus");
0178: errln("sdrf %bogus didn't fail");
0179: } catch (Exception e) {
0180: logln("Got the expected exception");
0181: }
0182:
0183: try {
0184: str = fmt3.format(2.3, names[0]);
0185: logln(str);
0186: str = fmt3.format(2.3, "%%foo");
0187: errln("format double %%foo didn't fail");
0188: } catch (Exception e) {
0189: logln("Got the expected exception");
0190: }
0191:
0192: try {
0193: str = fmt3.format(123L, names[0]);
0194: logln(str);
0195: str = fmt3.format(123L, "%%foo");
0196: errln("format double %%foo didn't fail");
0197: } catch (Exception e) {
0198: logln("Got the expected exception");
0199: }
0200:
0201: RuleBasedNumberFormat fmt4 = new RuleBasedNumberFormat(
0202: fracRules, Locale.ENGLISH);
0203: RuleBasedNumberFormat fmt5 = new RuleBasedNumberFormat(
0204: fracRules, Locale.ENGLISH);
0205: str = fmt4.toString();
0206: logln(str);
0207: if (!fmt4.equals(fmt5)) {
0208: errln("duplicate 2 equality failed");
0209: }
0210: str = fmt4.format(123L);
0211: logln(str);
0212: try {
0213: Number num = fmt4.parse(str);
0214: logln(num.toString());
0215: } catch (Exception e) {
0216: errln("parse caught exception");
0217: }
0218:
0219: str = fmt4.format(.000123);
0220: logln(str);
0221: try {
0222: Number num = fmt4.parse(str);
0223: logln(num.toString());
0224: } catch (Exception e) {
0225: errln("parse caught exception");
0226: }
0227:
0228: str = fmt4.format(456.000123);
0229: logln(str);
0230: try {
0231: Number num = fmt4.parse(str);
0232: logln(num.toString());
0233: } catch (Exception e) {
0234: errln("parse caught exception");
0235: }
0236: }
0237:
0238: public void TestUndefinedSpellout() {
0239: Locale greek = new Locale("el", "", "");
0240: RuleBasedNumberFormat[] formatters = {
0241: new RuleBasedNumberFormat(greek,
0242: RuleBasedNumberFormat.SPELLOUT),
0243: new RuleBasedNumberFormat(greek,
0244: RuleBasedNumberFormat.ORDINAL),
0245: new RuleBasedNumberFormat(greek,
0246: RuleBasedNumberFormat.DURATION), };
0247:
0248: String[] data = { "0", "1", "15", "20", "23", "73", "88",
0249: "100", "106", "127", "200", "579", "1,000", "2,000",
0250: "3,004", "4,567", "15,943", "105,000", "2,345,678",
0251: "-36", "-36.91215", "234.56789" };
0252:
0253: NumberFormat decFormat = NumberFormat.getInstance(Locale.US);
0254: for (int j = 0; j < formatters.length; ++j) {
0255: com.ibm.icu.text.NumberFormat formatter = formatters[j];
0256: logln("formatter[" + j + "]");
0257: for (int i = 0; i < data.length; ++i) {
0258: try {
0259: String result = formatter.format(decFormat
0260: .parse(data[i]));
0261: logln("[" + i + "] " + data[i] + " ==> " + result);
0262: } catch (Exception e) {
0263: errln("formatter[" + j + "], data[" + i + "] "
0264: + data[i] + " threw exception "
0265: + e.getMessage());
0266: }
0267: }
0268: }
0269: }
0270:
0271: /**
0272: * Perform a simple spot check on the English spellout rules
0273: */
0274: public void TestEnglishSpellout() {
0275: RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(
0276: Locale.US, RuleBasedNumberFormat.SPELLOUT);
0277: String[][] testData = {
0278: { "1", "one" },
0279: { "15", "fifteen" },
0280: { "20", "twenty" },
0281: { "23", "twenty-three" },
0282: { "73", "seventy-three" },
0283: { "88", "eighty-eight" },
0284: { "100", "one hundred" },
0285: { "106", "one hundred and six" },
0286: { "127", "one hundred and twenty-seven" },
0287: { "200", "two hundred" },
0288: { "579", "five hundred and seventy-nine" },
0289: { "1,000", "one thousand" },
0290: { "2,000", "two thousand" },
0291: { "3,004", "three thousand and four" },
0292: { "4,567", "four thousand five hundred and sixty-seven" },
0293: { "15,943",
0294: "fifteen thousand nine hundred and forty-three" },
0295: {
0296: "2,345,678",
0297: "two million, three hundred and forty-five "
0298: + "thousand, six hundred and seventy-eight" },
0299: { "-36", "minus thirty-six" },
0300: { "234.567",
0301: "two hundred and thirty-four point five six seven" } };
0302:
0303: doTest(formatter, testData, true);
0304:
0305: formatter.setLenientParseMode(true);
0306: String[][] lpTestData = {
0307: { "FOurhundred thiRTY six", "436" },
0308: // test spaces before fifty-7 causing lenient parse match of "fifty-" to " fifty"
0309: // leaving "-7" for remaining parse, resulting in 2643 as the parse result.
0310: { "fifty-7", "57" }, { " fifty-7", "57" },
0311: { " fifty-7", "57" },
0312: { "2 thousand six HUNDRED fifty-7", "2,657" },
0313: { "fifteen hundred and zero", "1,500" } };
0314: doLenientParseTest(formatter, lpTestData);
0315: }
0316:
0317: /**
0318: * Perform a simple spot check on the English ordinal-abbreviation rules
0319: */
0320: public void TestOrdinalAbbreviations() {
0321: RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(
0322: Locale.US, RuleBasedNumberFormat.ORDINAL);
0323: String[][] testData = { { "1", "1st" }, { "2", "2nd" },
0324: { "3", "3rd" }, { "4", "4th" }, { "7", "7th" },
0325: { "10", "10th" }, { "11", "11th" }, { "13", "13th" },
0326: { "20", "20th" }, { "21", "21st" }, { "22", "22nd" },
0327: { "23", "23rd" }, { "24", "24th" }, { "33", "33rd" },
0328: { "102", "102nd" }, { "312", "312th" },
0329: { "12,345", "12,345th" } };
0330:
0331: doTest(formatter, testData, false);
0332: }
0333:
0334: /**
0335: * Perform a simple spot check on the duration-formatting rules
0336: */
0337: public void TestDurations() {
0338: RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(
0339: Locale.US, RuleBasedNumberFormat.DURATION);
0340: String[][] testData = {
0341: { "3,600", "1:00:00" }, //move me and I fail
0342: { "0", "0 sec." }, { "1", "1 sec." },
0343: { "24", "24 sec." }, { "60", "1:00" },
0344: { "73", "1:13" }, { "145", "2:25" },
0345: { "666", "11:06" },
0346: // { "3,600", "1:00:00" },
0347: { "3,740", "1:02:20" }, { "10,293", "2:51:33" } };
0348:
0349: doTest(formatter, testData, true);
0350:
0351: formatter.setLenientParseMode(true);
0352: String[][] lpTestData = { { "2-51-33", "10,293" } };
0353: doLenientParseTest(formatter, lpTestData);
0354: }
0355:
0356: /**
0357: * Perform a simple spot check on the Spanish spellout rules
0358: */
0359: public void TestSpanishSpellout() {
0360: RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(
0361: new Locale("es", "es", ""),
0362: RuleBasedNumberFormat.SPELLOUT);
0363: String[][] testData = {
0364: { "1", "uno" },
0365: { "6", "seis" },
0366: { "16", "diecis\u00e9is" },
0367: { "20", "veinte" },
0368: { "24", "veinticuatro" },
0369: { "26", "veintis\u00e9is" },
0370: { "73", "setenta y tres" },
0371: { "88", "ochenta y ocho" },
0372: { "100", "cien" },
0373: { "106", "ciento seis" },
0374: { "127", "ciento veintisiete" },
0375: { "200", "doscientos" },
0376: { "579", "quinientos setenta y nueve" },
0377: { "1,000", "mil" },
0378: { "2,000", "dos mil" },
0379: { "3,004", "tres mil cuatro" },
0380: { "4,567", "cuatro mil quinientos sesenta y siete" },
0381: { "15,943", "quince mil novecientos cuarenta y tres" },
0382: {
0383: "2,345,678",
0384: "dos mill\u00f3n trescientos cuarenta y cinco mil "
0385: + "seiscientos setenta y ocho" },
0386: { "-36", "menos treinta y seis" },
0387: { "234.567",
0388: "doscientos treinta y cuatro punto cinco seis siete" } };
0389:
0390: doTest(formatter, testData, true);
0391: }
0392:
0393: /**
0394: * Perform a simple spot check on the French spellout rules
0395: */
0396: public void TestFrenchSpellout() {
0397: RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(
0398: Locale.FRANCE, RuleBasedNumberFormat.SPELLOUT);
0399: String[][] testData = {
0400: { "1", "un" },
0401: { "15", "quinze" },
0402: { "20", "vingt" },
0403: { "21", "vingt-et-un" },
0404: { "23", "vingt-trois" },
0405: { "62", "soixante-deux" },
0406: { "70", "soixante-dix" },
0407: { "71", "soixante et onze" },
0408: { "73", "soixante-treize" },
0409: { "80", "quatre-vingts" },
0410: { "88", "quatre-vingt-huit" },
0411: { "100", "cent" },
0412: { "106", "cent six" },
0413: { "127", "cent vingt-sept" },
0414: { "200", "deux cents" },
0415: { "579", "cinq cents soixante-dix-neuf" },
0416: { "1,000", "mille" },
0417: { "1,123", "onze cents vingt-trois" },
0418: { "1,594", "mille cinq cents quatre-vingt-quatorze" },
0419: { "2,000", "deux mille" },
0420: { "3,004", "trois mille quatre" },
0421: { "4,567", "quatre mille cinq cents soixante-sept" },
0422: { "15,943", "quinze mille neuf cents quarante-trois" },
0423: {
0424: "2,345,678",
0425: "deux million trois cents quarante-cinq mille "
0426: + "six cents soixante-dix-huit" },
0427: { "-36", "moins trente-six" },
0428: { "234.567",
0429: "deux cents trente-quatre virgule cinq six sept" } };
0430:
0431: doTest(formatter, testData, true);
0432:
0433: formatter.setLenientParseMode(true);
0434: String[][] lpTestData = { { "trente-un", "31" },
0435: { "un cents quatre vingt dix huit", "198" } };
0436: doLenientParseTest(formatter, lpTestData);
0437: }
0438:
0439: /**
0440: * Perform a simple spot check on the Swiss French spellout rules
0441: */
0442: public void TestSwissFrenchSpellout() {
0443: RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(
0444: new Locale("fr", "CH", ""),
0445: RuleBasedNumberFormat.SPELLOUT);
0446: String[][] testData = {
0447: { "1", "un" },
0448: { "15", "quinze" },
0449: { "20", "vingt" },
0450: { "21", "vingt-et-un" },
0451: { "23", "vingt-trois" },
0452: { "62", "soixante-deux" },
0453: { "70", "septante" },
0454: { "71", "septante-et-un" },
0455: { "73", "septante-trois" },
0456: { "80", "huitante" },
0457: { "88", "huitante-huit" },
0458: { "100", "cent" },
0459: { "106", "cent six" },
0460: { "127", "cent vingt-sept" },
0461: { "200", "deux cents" },
0462: { "579", "cinq cents septante-neuf" },
0463: { "1,000", "mille" },
0464: { "1,123", "onze cents vingt-trois" },
0465: { "1,594", "mille cinq cents nonante-quatre" },
0466: { "2,000", "deux mille" },
0467: { "3,004", "trois mille quatre" },
0468: { "4,567", "quatre mille cinq cents soixante-sept" },
0469: { "15,943", "quinze mille neuf cents quarante-trois" },
0470: {
0471: "2,345,678",
0472: "deux million trois cents quarante-cinq mille "
0473: + "six cents septante-huit" },
0474: { "-36", "moins trente-six" },
0475: { "234.567",
0476: "deux cents trente-quatre virgule cinq six sept" } };
0477:
0478: doTest(formatter, testData, true);
0479: }
0480:
0481: /**
0482: * Perform a simple spot check on the Italian spellout rules
0483: */
0484: public void TestItalianSpellout() {
0485: RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(
0486: Locale.ITALIAN, RuleBasedNumberFormat.SPELLOUT);
0487: String[][] testData = {
0488: { "1", "uno" },
0489: { "15", "quindici" },
0490: { "20", "venti" },
0491: { "23", "ventitre" },
0492: { "73", "settantatre" },
0493: { "88", "ottantotto" },
0494: { "100", "cento" },
0495: { "106", "centosei" },
0496: { "108", "centotto" },
0497: { "127", "centoventisette" },
0498: { "181", "centottantuno" },
0499: { "200", "duecento" },
0500: { "579", "cinquecentosettantanove" },
0501: { "1,000", "mille" },
0502: { "2,000", "duemila" },
0503: { "3,004", "tremilaquattro" },
0504: { "4,567", "quattromilacinquecentosessantasette" },
0505: { "15,943", "quindicimilanovecentoquarantatre" },
0506: { "-36", "meno trentisei" },
0507: { "234.567",
0508: "duecentotrentiquattro virgola cinque sei sette" } };
0509:
0510: doTest(formatter, testData, true);
0511: }
0512:
0513: /**
0514: * Perform a simple spot check on the German spellout rules
0515: */
0516: public void TestGermanSpellout() {
0517: RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(
0518: Locale.GERMANY, RuleBasedNumberFormat.SPELLOUT);
0519: String[][] testData = {
0520: { "1", "eins" },
0521: { "15", "f\u00fcnfzehn" },
0522: { "20", "zwanzig" },
0523: { "23", "dreiundzwanzig" },
0524: { "73", "dreiundsiebzig" },
0525: { "88", "achtundachtzig" },
0526: { "100", "hundert" },
0527: { "106", "hundertsechs" },
0528: { "127", "hundertsiebenundzwanzig" },
0529: { "200", "zweihundert" },
0530: { "579", "f\u00fcnfhundertneunundsiebzig" },
0531: { "1,000", "tausend" },
0532: { "2,000", "zweitausend" },
0533: { "3,004", "dreitausendvier" },
0534: { "4,567",
0535: "viertausendf\u00fcnfhundertsiebenundsechzig" },
0536: { "15,943",
0537: "f\u00fcnfzehntausendneunhundertdreiundvierzig" },
0538: {
0539: "2,345,678",
0540: "zwei Millionen dreihundertf\u00fcnfundvierzigtausend"
0541: + "sechshundertachtundsiebzig" } };
0542:
0543: doTest(formatter, testData, true);
0544:
0545: formatter.setLenientParseMode(true);
0546: String[][] lpTestData = { {
0547: "ein Tausend sechs Hundert fuenfunddreissig", "1,635" } };
0548: doLenientParseTest(formatter, lpTestData);
0549: }
0550:
0551: /**
0552: * Perform a simple spot check on the Thai spellout rules
0553: */
0554: public void TestThaiSpellout() {
0555: RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(
0556: new Locale("th", "TH", ""),
0557: RuleBasedNumberFormat.SPELLOUT);
0558: String[][] testData = {
0559: { "0", "\u0e28\u0e39\u0e19\u0e22\u0e4c" },
0560: { "1", "\u0e2b\u0e19\u0e36\u0e48\u0e07" },
0561: { "10", "\u0e2a\u0e34\u0e1a" },
0562: { "11", "\u0e2a\u0e34\u0e1a\u0e40\u0e2d\u0e47\u0e14" },
0563: { "21",
0564: "\u0e22\u0e35\u0e48\u0e2a\u0e34\u0e1a\u0e40\u0e2d\u0e47\u0e14" },
0565: {
0566: "101",
0567: "\u0e2b\u0e19\u0e36\u0e48\u0e07\u0e23\u0e49\u0e2d\u0e22\u0e2b\u0e19\u0e36\u0e48\u0e07" },
0568: {
0569: "1.234",
0570: "\u0e2b\u0e19\u0e36\u0e48\u0e07\u0e08\u0e38\u0e14\u0e2a\u0e2d\u0e07\u0e2a\u0e32\u0e21\u0e2a\u0e35\u0e48" },
0571: {
0572: "21.45",
0573: "\u0e22\u0e35\u0e48\u0e2a\u0e34\u0e1a\u0e40\u0e2d\u0e47\u0e14\u0e08\u0e38\u0e14\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" },
0574: {
0575: "22.45",
0576: "\u0e22\u0e35\u0e48\u0e2a\u0e34\u0e1a\u0e2a\u0e2d\u0e07\u0e08\u0e38\u0e14\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" },
0577: {
0578: "23.45",
0579: "\u0e22\u0e35\u0e48\u0e2a\u0e34\u0e1a\u0e2a\u0e32\u0e21\u0e08\u0e38\u0e14\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" },
0580: {
0581: "123.45",
0582: "\u0e2b\u0e19\u0e36\u0e48\u0e07\u0e23\u0e49\u0e2d\u0e22\u0e22\u0e35\u0e48\u0e2a\u0e34\u0e1a\u0e2a\u0e32\u0e21\u0e08\u0e38\u0e14\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" },
0583: {
0584: "12,345.678",
0585: "\u0E2B\u0E19\u0E36\u0E48\u0E07\u0E2B\u0E21\u0E37\u0E48\u0E19\u0E2A\u0E2D\u0E07\u0E1E\u0E31\u0E19\u0E2A\u0E32\u0E21\u0E23\u0E49\u0E2D\u0E22\u0E2A\u0E35\u0E48\u0E2A\u0E34\u0E1A\u0E2B\u0E49\u0E32\u0E08\u0E38\u0E14\u0E2B\u0E01\u0E40\u0E08\u0E47\u0E14\u0E41\u0E1B\u0E14" }, };
0586:
0587: doTest(formatter, testData, true);
0588:
0589: /*
0590: formatter.setLenientParseMode(true);
0591: String[][] lpTestData = {
0592: { "ein Tausend sechs Hundert fuenfunddreissig", "1,635" }
0593: };
0594: doLenientParseTest(formatter, lpTestData);
0595: */
0596: }
0597:
0598: public void TestFractionalRuleSet() {
0599:
0600: RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(
0601: fracRules, Locale.ENGLISH);
0602:
0603: String[][] testData = { { "0", "0" }, { "1", "1" },
0604: { "10", "10" }, { ".1", "1/10" }, { ".11", "1/9" },
0605: { ".125", "1/8" }, { ".1428", "1/7" },
0606: { ".1667", "1/6" }, { ".2", "1/5" }, { ".25", "1/4" },
0607: { ".333", "1/3" }, { ".5", "1/2" },
0608: { "1.1", "1 1/10" }, { "2.11", "2 1/9" },
0609: { "3.125", "3 1/8" }, { "4.1428", "4 1/7" },
0610: { "5.1667", "5 1/6" }, { "6.2", "6 1/5" },
0611: { "7.25", "7 1/4" }, { "8.333", "8 1/3" },
0612: { "9.5", "9 1/2" }, { ".2222", "2/9" },
0613: { ".4444", "4/9" }, { ".5555", "5/9" },
0614: { "1.2856", "1 2/7" } };
0615: doTest(formatter, testData, false); // exact values aren't parsable from fractions
0616: }
0617:
0618: public void TestSwedishSpellout() {
0619: Locale locale = new Locale("sv", "", "");
0620: RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(
0621: locale, RuleBasedNumberFormat.SPELLOUT);
0622:
0623: String[][] testDataDefault = {
0624: { "101", "etthundra\u00aden" },
0625: { "123", "etthundra\u00adtjugotre" },
0626: { "1,001", "ettusen en" },
0627: { "1,100", "ettusen etthundra" },
0628: { "1,101", "ettusen etthundra\u00aden" },
0629: { "1,234", "ettusen tv\u00e5hundra\u00adtrettiofyra" },
0630: { "10,001", "tio\u00adtusen en" },
0631: { "11,000", "elva\u00adtusen" },
0632: { "12,000", "tolv\u00adtusen" },
0633: { "20,000", "tjugo\u00adtusen" },
0634: { "21,000", "tjugoen\u00adtusen" },
0635: { "21,001", "tjugoen\u00adtusen en" },
0636: { "200,000", "tv\u00e5hundra\u00adtusen" },
0637: { "201,000", "tv\u00e5hundra\u00aden\u00adtusen" },
0638: { "200,200", "tv\u00e5hundra\u00adtusen tv\u00e5hundra" },
0639: { "2,002,000", "tv\u00e5 miljoner tv\u00e5\u00adtusen" },
0640: {
0641: "12,345,678",
0642: "tolv miljoner trehundra\u00adfyrtiofem\u00adtusen sexhundra\u00adsjuttio\u00e5tta" },
0643: {
0644: "123,456.789",
0645: "etthundra\u00adtjugotre\u00adtusen fyrahundra\u00adfemtiosex komma sju \u00e5tta nio" },
0646: { "-12,345.678",
0647: "minus tolv\u00adtusen trehundra\u00adfyrtiofem komma sex sju \u00e5tta" } };
0648:
0649: logln("testing default rules");
0650: doTest(formatter, testDataDefault, true);
0651:
0652: String[][] testDataNeutrum = { { "101", "etthundra\u00adett" },
0653: { "1,001", "ettusen ett" },
0654: { "1,101", "ettusen etthundra\u00adett" },
0655: { "10,001", "tio\u00adtusen ett" },
0656: { "21,001", "tjugoen\u00adtusen ett" } };
0657:
0658: formatter.setDefaultRuleSet("%neutrum");
0659: logln("testing neutrum rules");
0660: doTest(formatter, testDataNeutrum, true);
0661:
0662: String[][] testDataYear = { { "101", "etthundra\u00adett" },
0663: { "900", "niohundra" },
0664: { "1,001", "tiohundra\u00adett" },
0665: { "1,100", "elvahundra" },
0666: { "1,101", "elvahundra\u00adett" },
0667: { "1,234", "tolvhundra\u00adtrettiofyra" },
0668: { "2,001", "tjugohundra\u00adett" },
0669: { "10,001", "tio\u00adtusen ett" } };
0670:
0671: formatter.setDefaultRuleSet("%year");
0672: logln("testing year rules");
0673: doTest(formatter, testDataYear, true);
0674: }
0675:
0676: public void TestBigNumbers() {
0677: BigInteger bigI = new BigInteger("1234567890", 10);
0678: StringBuffer buf = new StringBuffer();
0679: RuleBasedNumberFormat fmt = new RuleBasedNumberFormat(
0680: RuleBasedNumberFormat.SPELLOUT);
0681: fmt.format(bigI, buf, null);
0682: logln("big int: " + buf.toString());
0683:
0684: //#ifndef FOUNDATION
0685: buf.setLength(0);
0686: BigDecimal bigD = new BigDecimal(bigI);
0687: fmt.format(bigD, buf, null);
0688: logln("big dec: " + buf.toString());
0689: //#endif
0690: }
0691:
0692: public void TestTrailingSemicolon() {
0693: String thaiRules = "%default:\n"
0694: + " -x: \u0e25\u0e1a>>;\n"
0695: + " x.x: <<\u0e08\u0e38\u0e14>>>;\n"
0696: + " \u0e28\u0e39\u0e19\u0e22\u0e4c; \u0e2b\u0e19\u0e36\u0e48\u0e07; \u0e2a\u0e2d\u0e07; \u0e2a\u0e32\u0e21;\n"
0697: + " \u0e2a\u0e35\u0e48; \u0e2b\u0e49\u0e32; \u0e2b\u0e01; \u0e40\u0e08\u0e47\u0e14; \u0e41\u0e1b\u0e14;\n"
0698: + " \u0e40\u0e01\u0e49\u0e32; \u0e2a\u0e34\u0e1a; \u0e2a\u0e34\u0e1a\u0e40\u0e2d\u0e47\u0e14;\n"
0699: + " \u0e2a\u0e34\u0e1a\u0e2a\u0e2d\u0e07; \u0e2a\u0e34\u0e1a\u0e2a\u0e32\u0e21;\n"
0700: + " \u0e2a\u0e34\u0e1a\u0e2a\u0e35\u0e48; \u0e2a\u0e34\u0e1a\u0e2b\u0e49\u0e32;\n"
0701: + " \u0e2a\u0e34\u0e1a\u0e2b\u0e01; \u0e2a\u0e34\u0e1a\u0e40\u0e08\u0e47\u0e14;\n"
0702: + " \u0e2a\u0e34\u0e1a\u0e41\u0e1b\u0e14; \u0e2a\u0e34\u0e1a\u0e40\u0e01\u0e49\u0e32;\n"
0703: + " 20: \u0e22\u0e35\u0e48\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n"
0704: + " 30: \u0e2a\u0e32\u0e21\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n"
0705: + " 40: \u0e2a\u0e35\u0e48\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n"
0706: + " 50: \u0e2b\u0e49\u0e32\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n"
0707: + " 60: \u0e2b\u0e01\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n"
0708: + " 70: \u0e40\u0e08\u0e47\u0e14\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n"
0709: + " 80: \u0e41\u0e1b\u0e14\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n"
0710: + " 90: \u0e40\u0e01\u0e49\u0e32\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n"
0711: + " 100: <<\u0e23\u0e49\u0e2d\u0e22[>>];\n"
0712: + " 1000: <<\u0e1e\u0e31\u0e19[>>];\n"
0713: + " 10000: <<\u0e2b\u0e21\u0e37\u0e48\u0e19[>>];\n"
0714: + " 100000: <<\u0e41\u0e2a\u0e19[>>];\n"
0715: + " 1,000,000: <<\u0e25\u0e49\u0e32\u0e19[>>];\n"
0716: + " 1,000,000,000: <<\u0e1e\u0e31\u0e19\u0e25\u0e49\u0e32\u0e19[>>];\n"
0717: + " 1,000,000,000,000: <<\u0e25\u0e49\u0e32\u0e19\u0e25\u0e49\u0e32\u0e19[>>];\n"
0718: + " 1,000,000,000,000,000: =#,##0=;\n"
0719: + "%%alt-ones:\n"
0720: + " \u0e28\u0e39\u0e19\u0e22\u0e4c;\n"
0721: + " \u0e40\u0e2d\u0e47\u0e14;\n"
0722: + " =%default=;\n ; ;; ";
0723:
0724: RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(
0725: thaiRules, new Locale("th", "TH", ""));
0726:
0727: String[][] testData = {
0728: { "0", "\u0e28\u0e39\u0e19\u0e22\u0e4c" },
0729: { "1", "\u0e2b\u0e19\u0e36\u0e48\u0e07" },
0730: {
0731: "123.45",
0732: "\u0e2b\u0e19\u0e36\u0e48\u0e07\u0e23\u0e49\u0e2d\u0e22\u0e22\u0e35\u0e48\u0e2a\u0e34\u0e1a\u0e2a\u0e32\u0e21\u0e08\u0e38\u0e14\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" } };
0733:
0734: doTest(formatter, testData, true);
0735: }
0736:
0737: public void TestSmallValues() {
0738: String[][] testData = {
0739: { "0.001", "zero point zero zero one" },
0740: { "0.0001", "zero point zero zero zero one" },
0741: { "0.00001", "zero point zero zero zero zero one" },
0742: { "0.000001", "zero point zero zero zero zero zero one" },
0743: { "0.0000001",
0744: "zero point zero zero zero zero zero zero one" },
0745: { "0.00000001",
0746: "zero point zero zero zero zero zero zero zero one" },
0747: { "0.000000001",
0748: "zero point zero zero zero zero zero zero zero zero one" },
0749: { "0.0000000001",
0750: "zero point zero zero zero zero zero zero zero zero zero one" },
0751: { "0.00000000001",
0752: "zero point zero zero zero zero zero zero zero zero zero zero one" },
0753: { "0.000000000001",
0754: "zero point zero zero zero zero zero zero zero zero zero zero zero one" },
0755: { "0.0000000000001",
0756: "zero point zero zero zero zero zero zero zero zero zero zero zero zero one" },
0757: {
0758: "0.00000000000001",
0759: "zero point zero zero zero zero zero zero zero zero zero zero zero zero zero one" },
0760: {
0761: "0.000000000000001",
0762: "zero point zero zero zero zero zero zero zero zero zero zero zero zero zero zero one" },
0763: { "10,000,000.001", "ten million point zero zero one" },
0764: { "10,000,000.0001",
0765: "ten million point zero zero zero one" },
0766: { "10,000,000.00001",
0767: "ten million point zero zero zero zero one" },
0768: { "10,000,000.000001",
0769: "ten million point zero zero zero zero zero one" },
0770: { "10,000,000.0000001",
0771: "ten million point zero zero zero zero zero zero one" },
0772: { "10,000,000.00000001",
0773: "ten million point zero zero zero zero zero zero zero one" },
0774: { "10,000,000.000000002",
0775: "ten million point zero zero zero zero zero zero zero zero two" },
0776: { "10,000,000", "ten million" },
0777: {
0778: "1,234,567,890.0987654",
0779: "one billion, two hundred and thirty-four million, five hundred and sixty-seven thousand, eight hundred and ninety point zero nine eight seven six five four" },
0780: {
0781: "123,456,789.9876543",
0782: "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine point nine eight seven six five four three" },
0783: {
0784: "12,345,678.87654321",
0785: "twelve million, three hundred and forty-five thousand, six hundred and seventy-eight point eight seven six five four three two one" },
0786: {
0787: "1,234,567.7654321",
0788: "one million, two hundred and thirty-four thousand, five hundred and sixty-seven point seven six five four three two one" },
0789: {
0790: "123,456.654321",
0791: "one hundred and twenty-three thousand, four hundred and fifty-six point six five four three two one" },
0792: { "12,345.54321",
0793: "twelve thousand three hundred and forty-five point five four three two one" },
0794: { "1,234.4321",
0795: "one thousand two hundred and thirty-four point four three two one" },
0796: { "123.321",
0797: "one hundred and twenty-three point three two one" },
0798: {
0799: "0.0000000011754944",
0800: "zero point zero zero zero zero zero zero zero zero one one seven five four nine four four" },
0801: {
0802: "0.000001175494351",
0803: "zero point zero zero zero zero zero one one seven five four nine four three five one" }, };
0804:
0805: RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(
0806: Locale.US, RuleBasedNumberFormat.SPELLOUT);
0807: doTest(formatter, testData, true);
0808: }
0809:
0810: public void TestRuleSetDisplayName() {
0811: ULocale.setDefault(ULocale.US);
0812: String[][] localizations = new String[][] {
0813: /* public rule sets*/
0814: { "%simplified", "%default", "%ordinal" },
0815: /* display names in "en_US" locale*/
0816: { "en_US", "Simplified", "Default", "Ordinal" },
0817: /* display names in "zh_Hans" locale*/
0818: { "zh_Hans", "\u7B80\u5316", "\u7F3A\u7701", "\u5E8F\u5217" },
0819: /* display names in a fake locale*/
0820: { "foo_Bar_BAZ", "Simplified", "Default", "Ordinal" } };
0821:
0822: //Construct RuleBasedNumberFormat by rule sets and localizations list
0823: RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(
0824: ukEnglish, localizations, ULocale.US);
0825: RuleBasedNumberFormat f2 = new RuleBasedNumberFormat(ukEnglish,
0826: localizations);
0827: assertTrue("Check the two formatters' equality", formatter
0828: .equals(f2));
0829:
0830: //get displayName by name
0831: String[] ruleSetNames = formatter.getRuleSetNames();
0832: for (int i = 0; i < ruleSetNames.length; i++) {
0833: logln("Rule set name: " + ruleSetNames[i]);
0834: String RSName_defLoc = formatter
0835: .getRuleSetDisplayName(ruleSetNames[i]);
0836: assertEquals("Display name in default locale",
0837: localizations[1][i + 1], RSName_defLoc);
0838: String RSName_loc = formatter.getRuleSetDisplayName(
0839: ruleSetNames[i], ULocale.CHINA);
0840: assertEquals("Display name in Chinese",
0841: localizations[2][i + 1], RSName_loc);
0842: }
0843:
0844: // getDefaultRuleSetName
0845: String defaultRS = formatter.getDefaultRuleSetName();
0846: //you know that the default rule set is %simplified according to rule sets string ukEnglish
0847: assertEquals("getDefaultRuleSetName", "%simplified", defaultRS);
0848:
0849: //get locales of localizations
0850: ULocale[] locales = formatter.getRuleSetDisplayNameLocales();
0851: for (int i = 0; i < locales.length; i++) {
0852: logln(locales[i].getName());
0853: }
0854:
0855: //get displayNames
0856: String[] RSNames_defLoc = formatter.getRuleSetDisplayNames();
0857: for (int i = 0; i < RSNames_defLoc.length; i++) {
0858: assertEquals("getRuleSetDisplayNames in default locale",
0859: localizations[1][i + 1], RSNames_defLoc[i]);
0860: }
0861:
0862: String[] RSNames_loc = formatter
0863: .getRuleSetDisplayNames(ULocale.UK);
0864: for (int i = 0; i < RSNames_loc.length; i++) {
0865: assertEquals("getRuleSetDisplayNames in English",
0866: localizations[1][i + 1], RSNames_loc[i]);
0867: }
0868:
0869: RSNames_loc = formatter.getRuleSetDisplayNames(ULocale.CHINA);
0870: for (int i = 0; i < RSNames_loc.length; i++) {
0871: assertEquals("getRuleSetDisplayNames in Chinese",
0872: localizations[2][i + 1], RSNames_loc[i]);
0873: }
0874:
0875: RSNames_loc = formatter.getRuleSetDisplayNames(new ULocale(
0876: "foo_Bar_BAZ"));
0877: for (int i = 0; i < RSNames_loc.length; i++) {
0878: assertEquals("getRuleSetDisplayNames in fake locale",
0879: localizations[3][i + 1], RSNames_loc[i]);
0880: }
0881: }
0882:
0883: public void TestAllLocales() {
0884: StringBuffer errors = null;
0885: ULocale[] locales = ULocale.getAvailableLocales();
0886: Random r = createRandom();
0887: String[] names = { " (spellout) ", " (ordinal) ",
0888: " (duration) " };
0889: for (int i = 0; i < locales.length; ++i) {
0890: ULocale loc = locales[i];
0891: for (int j = 0; j < 3; ++j) {
0892: try {
0893: RuleBasedNumberFormat fmt = new RuleBasedNumberFormat(
0894: loc, j + 1);
0895: float n = ((int) (r.nextInt(1000) - 300)) / 16f;
0896: String s = fmt.format(n);
0897: if (isVerbose()) {
0898: logln(loc.getName() + names[j] + "success: "
0899: + n + " -> " + s);
0900: }
0901: } catch (Exception e) {
0902: String msg = loc.getName() + names[j] + "ERROR:"
0903: + e.getMessage();
0904: if (isVerbose()) {
0905: logln(msg);
0906: }
0907: if (errors == null) {
0908: errors = new StringBuffer();
0909: }
0910: errors.append("\n" + msg);
0911: }
0912: }
0913: }
0914: if (errors != null) {
0915: errln(errors.toString());
0916: }
0917: }
0918:
0919: void doTest(RuleBasedNumberFormat formatter, String[][] testData,
0920: boolean testParsing) {
0921: // NumberFormat decFmt = NumberFormat.getInstance(Locale.US);
0922: NumberFormat decFmt = new DecimalFormat(
0923: "#,###.################");
0924: try {
0925: for (int i = 0; i < testData.length; i++) {
0926: String number = testData[i][0];
0927: String expectedWords = testData[i][1];
0928: logln("test[" + i + "] number: " + number + " target: "
0929: + expectedWords);
0930: Number num = decFmt.parse(number);
0931: String actualWords = formatter.format(num);
0932:
0933: if (!actualWords.equals(expectedWords)) {
0934: errln("Spot check format failed: for " + number
0935: + ", expected\n " + expectedWords
0936: + ", but got\n " + actualWords);
0937: } else if (testParsing) {
0938: String actualNumber = decFmt.format(formatter
0939: .parse(actualWords));
0940:
0941: if (!actualNumber.equals(number)) {
0942: errln("Spot check parse failed: for "
0943: + actualWords + ", expected " + number
0944: + ", but got " + actualNumber);
0945: }
0946: }
0947: }
0948: } catch (Throwable e) {
0949: e.printStackTrace();
0950: errln("Test failed with exception: " + e.toString());
0951: }
0952: }
0953:
0954: void doLenientParseTest(RuleBasedNumberFormat formatter,
0955: String[][] testData) {
0956: NumberFormat decFmt = NumberFormat.getInstance(Locale.US);
0957:
0958: try {
0959: for (int i = 0; i < testData.length; i++) {
0960: String words = testData[i][0];
0961: String expectedNumber = testData[i][1];
0962: String actualNumber = decFmt.format(formatter
0963: .parse(words));
0964:
0965: if (!actualNumber.equals(expectedNumber)) {
0966: errln("Lenient-parse spot check failed: for "
0967: + words + ", expected " + expectedNumber
0968: + ", but got " + actualNumber);
0969: }
0970: }
0971: } catch (Throwable e) {
0972: errln("Test failed with exception: " + e.toString());
0973: e.printStackTrace();
0974: }
0975: }
0976:
0977: /**
0978: * Spellout rules for U.K. English.
0979: * I borrow the rule sets for TestRuleSetDisplayName()
0980: */
0981: public static final String ukEnglish = "%simplified:\n"
0982: + " -x: minus >>;\n"
0983: + " x.x: << point >>;\n"
0984: + " zero; one; two; three; four; five; six; seven; eight; nine;\n"
0985: + " ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen;\n"
0986: + " seventeen; eighteen; nineteen;\n"
0987: + " 20: twenty[->>];\n"
0988: + " 30: thirty[->>];\n"
0989: + " 40: forty[->>];\n"
0990: + " 50: fifty[->>];\n"
0991: + " 60: sixty[->>];\n"
0992: + " 70: seventy[->>];\n"
0993: + " 80: eighty[->>];\n"
0994: + " 90: ninety[->>];\n"
0995: + " 100: << hundred[ >>];\n"
0996: + " 1000: << thousand[ >>];\n"
0997: + " 1,000,000: << million[ >>];\n"
0998: + " 1,000,000,000,000: << billion[ >>];\n"
0999: + " 1,000,000,000,000,000: =#,##0=;\n"
1000: + "%alt-teens:\n"
1001: + " =%simplified=;\n"
1002: + " 1000>: <%%alt-hundreds<[ >>];\n"
1003: + " 10,000: =%simplified=;\n"
1004: + " 1,000,000: << million[ >%simplified>];\n"
1005: + " 1,000,000,000,000: << billion[ >%simplified>];\n"
1006: + " 1,000,000,000,000,000: =#,##0=;\n"
1007: + "%%alt-hundreds:\n"
1008: + " 0: SHOULD NEVER GET HERE!;\n"
1009: + " 10: <%simplified< thousand;\n"
1010: + " 11: =%simplified= hundred>%%empty>;\n"
1011: + "%%empty:\n"
1012: + " 0:;"
1013: + "%ordinal:\n"
1014: + " zeroth; first; second; third; fourth; fifth; sixth; seventh;\n"
1015: + " eighth; ninth;\n"
1016: + " tenth; eleventh; twelfth; thirteenth; fourteenth;\n"
1017: + " fifteenth; sixteenth; seventeenth; eighteenth;\n"
1018: + " nineteenth;\n"
1019: + " twentieth; twenty->>;\n"
1020: + " 30: thirtieth; thirty->>;\n"
1021: + " 40: fortieth; forty->>;\n"
1022: + " 50: fiftieth; fifty->>;\n"
1023: + " 60: sixtieth; sixty->>;\n"
1024: + " 70: seventieth; seventy->>;\n"
1025: + " 80: eightieth; eighty->>;\n"
1026: + " 90: ninetieth; ninety->>;\n"
1027: + " 100: <%simplified< hundredth; <%simplified< hundred >>;\n"
1028: + " 1000: <%simplified< thousandth; <%simplified< thousand >>;\n"
1029: + " 1,000,000: <%simplified< millionth; <%simplified< million >>;\n"
1030: + " 1,000,000,000,000: <%simplified< billionth;\n"
1031: + " <%simplified< billion >>;\n"
1032: + " 1,000,000,000,000,000: =#,##0=;" + "%default:\n"
1033: + " -x: minus >>;\n" + " x.x: << point >>;\n"
1034: + " =%simplified=;\n"
1035: + " 100: << hundred[ >%%and>];\n"
1036: + " 1000: << thousand[ >%%and>];\n"
1037: + " 100,000>>: << thousand[>%%commas>];\n"
1038: + " 1,000,000: << million[>%%commas>];\n"
1039: + " 1,000,000,000,000: << billion[>%%commas>];\n"
1040: + " 1,000,000,000,000,000: =#,##0=;\n" + "%%and:\n"
1041: + " and =%default=;\n" + " 100: =%default=;\n"
1042: + "%%commas:\n" + " ' and =%default=;\n"
1043: + " 100: , =%default=;\n"
1044: + " 1000: , <%default< thousand, >%default>;\n"
1045: + " 1,000,000: , =%default=;" + "%%lenient-parse:\n"
1046: + " & ' ' , ',' ;\n";
1047:
1048: }
|