Numerical Systems

Formatting numbers is straight forward in Java.  Many developers overlook this aspect of localization.  Numeric systems vary around the world, and even more importantly the delimiters and separators vary.  ICU4J provides even more capabilities

Format and parse an integer

Problem:

You want to format and parse integer values.

Solution:

The Java NumberFormat class makes formatting and parsing a number is localized manner easy and efficient.  Simple specify the locale when retrieving the NumberFormat instance.

 

To format and parse a number in Hindi:

//Get a locale.  Hindi in India here.
ULocale hindi = new ULocale("hi_IN");
//Get an instance of an integer format.
NumberFormat nf = NumberFormat.getIntegerInstance(hindi);
//format and output.  The decimal is cut off and rounded.
String f = nf.format(1234234234.556);
System.out.println(f);

//Parse the value.  We must handle the potential ParseException
try {
    System.out.println(nf.parse("१,२३,४२,३४,२३५"));
} catch (ParseException e) {
    e.printStackTrace();
}

 


The output:

१,२३,४२,३४,२३५
1234234235

Format and parse a decimal

Problem:

You want to format and parse decimal values.

Solution:

Localized formatting of decimal values is easy in Java.  It can be accomplished by passing the number into the getInstance method on the NumberFormat class.  Then simply call format and parse.

 

To format and parse a decimal value for Arabic:

//Get a locale.  We use Arabic without a country here.
ULocale arabic = new ULocale("ar");
//Get a decimal formatter instance
NumberFormat nf = NumberFormat.getInstance(arabic);
//format and output
String f = nf.format(123456.789);
System.out.println(f);
//Parse the value.  We must handle the potential ParseException
try {
   System.out.println(nf.parse("١٢٣٬٤٥٦٫٧٨٩"));
} catch (ParseException e) {
    e.printStackTrace();
}

 


The output :

١٢٣٬٤٥٦٫٧٨٩
123456.789

Format and parse a percent

Problem:

You want to format and parse percent values.

Solution:

The Java NumberFormat class makes it easy to create a localized format for a percent value.  Simply pass the locale when retrieving your instance.  The format will see 1 as 100% and .1 as 10%.

 

To format and parse a percent value for Brazillian Portuguese:

//Get a locale.  In this case Portuguese in Brazil
ULocale pt = new ULocale("pt_BR");
//Get an instance of a percent formatter
NumberFormat nf = NumberFormat.getPercentInstance(pt);
//format and output.  1 == 100% and .5 = 50%
String f = nf.format(.78);
System.out.println(f);
//Parse the value.  We must handle the potential ParseException
try {
    System.out.println(nf.parse("78%"));
} catch (ParseException e) {
    e.printStackTrace();
}

 


The output:

78%
0.78

Format and parse a currency

Problem:

You want to format and parse localized currency values.

Solution:

Currency formatting at its most basic is straight forward in Java programming.  Simply retrieve a currency instance of the NumberFormat class and format your number.

 

To format a currency for Japanese for Japan:

//Get a locale.
Locale ja = new Locale("ja","JP");
//Get a currency instance
NumberFormat nf = NumberFormat.getCurrencyInstance(ja);
//format and output.  Notice the rounding is limited to two place on the output.  This is
//Governed by the currency
String f = nf.format(123456.789);
System.out.println(f);

//Parse the value.  We must handle the potential ParseException
try {
    System.out.println(nf.parse("¥123,457"));
} catch (ParseException e) {
    e.printStackTrace();
}

 


The output:

¥123,457
123457

 

Currencies  have a rounding increment that is also important.  A US dollar has cents, and so a currency should be rounded two decimal places.  A Japanese Yen should be rounded to the nearest integer.  If you specify a currency other than the default for the locale the rounding will reflect the locale and not the currency.

 

Format Ordinal Numbers

 Problem:

You want to format an ordinal number like "1st" or "2nd".

Solution:

Java programmers can handle ordinal number formatting by leveraging ICU4J's RuleBasedNumberFormat class.  

 

An ordinal number is a number like "1st" "2nd" etc.

 

To format an ordinal number:

//Get a RuleBasedNumberFormat appropriate for English ordinal format

RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat(ULocale.ENGLISH,RuleBasedNumberFormat.ORDINAL);

//Format the number

System.out.println(rbnf.format(21));

 


The output:

21st

 

Parse a spelled-out number

Problem:

You want to convert a spelled out number to a Number.

Solution:

Parsing a formatted number in Java takes a new twist when the number is fully spelled out.   This can be easily accomplished thanks to the ICU4J library from IBM.  

 

To parse a spelled out number:

//Get a RuleBasedNumberFormat appropriate for French spellout

RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat(ULocale.ENGLISH,RuleBasedNumberFormat.SPELLOUT);

//The String to parse

String number = "three hundred and forty-five";

//We need to handle the potential ParseException

try

{

    //Parse the number

    System.out.println(rbnf.parse(number));

}

catch (ParseException e)

{

    e.printStackTrace();

}

 

The output:
345

 

The same thing for a French Locale:

RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat(ULocale.FRENCH,RuleBasedNumberFormat.SPELLOUT);

String number = "trois cents quarante-cinq";

try

{

    System.out.println(rbnf.parse(number));

}

catch (ParseException e)

{

    // TODO Auto-generated catch block

    e.printStackTrace();

}

 

Spell out a numeric value

Problem:

You want to spell out a localized number like "thirty-six."

Solution:

ICU4J provides some number formatting capabilities that core Java does not.  One of those features is the ability to spell out a numeric value. 

 

This uses the RuleBasedNumberFormat class to convert a numeric value to a spelled out value.  In other words "75" can be converted to "seventy-five."  This can also be combined with MessageFormat.

 

To spell out a numeric value:

//Get a RuleBasedNumberFormat appropriate for French spellout

RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat(ULocale.FRENCH,RuleBasedNumberFormat.SPELLOUT);

//Call format passing in the numeric value to be formatted

System.out.println(rbnf.format(345));

 

 


 The output:

trois cents quarante-cinq

Use a non-default currency

 

Problem:

You want to use a currency other than the default for the region.

Solution:

We can specify a currency separate from a region.  This will give us a numeric format that is appropriate to the locale, but use a currency code for the specified locale.

//Get a locale.
Locale italian = new Locale("it","IT");
//Get a currency instance
Currency c = Currency.getInstance("JPY");
//Get a currency instance
NumberFormat nf = NumberFormat.getCurrencyInstance(italian);
nf.setCurrency(c);
//format and output.  Notice the rounding is not limited to two place on the output.  Rounding
//is now governed by the locale.  Also notice we now use the ISO code istead of a symbol
String f = nf.format(123456.789);
System.out.println(f);

//Parse the value.  We must handle the potential ParseException
//Notice that we can not handle the '¥' mark in the parse
try {
    System.out.println(nf.parse("JPY 123.456,79"));
} catch (ParseException e) {
    e.printStackTrace();
}


 

The output:

JPY 123.456,79
123456.79