1. Overview
In this tutorial, we’ll see how we can convert a monetary amount into words-representation in Java.
We’ll also see how a custom implementation could look like, via an external library – Tradukisto.
2. Implementation
Let’s first start with our own implementation. The first step is to declare two String arrays with the following elements:
public static String[] ones = { "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" }; public static String[] tens = { "", // 0 "", // 1 "twenty", // 2 "thirty", // 3 "forty", // 4 "fifty", // 5 "sixty", // 6 "seventy", // 7 "eighty", // 8 "ninety" // 9 };
When we receive an input, we’ll need to handle the invalid values (zero and negative values). Once a valid input is received, we can extract the number of dollars and cents into variables:
long dollars = (long) money; long cents = Math.round((money - dollars) * 100);
If the number given is less than 20, then we’ll get the appropriate ones’ element from the array based on the index:
if (n < 20) { return ones[(int) n]; }
We’ll use a similar approach for numbers less than 100, but now we have to use tens array as well:
if (n < 100) { return tens[(int) n / 10] + ((n % 10 != 0) ? " " : "") + ones[(int) n % 10]; }
We do this similarly for numbers that are less than one thousand.
Next, we use recursive calls to deal with numbers that are less than one million, as shown below:
if (n < 1_000_000) { return convert(n / 1000) + " thousand" + ((n % 1000 != 0) ? " " : "") + convert(n % 1000); }
The same approach is used for numbers that are less than one billion, and so on.
Here is the main method that can be called to do this conversion:
public static String getMoneyIntoWords(double money) { long dollars = (long) money; long cents = Math.round((money - dollars) * 100); if (money == 0D) { return ""; } if (money < 0) { return INVALID_INPUT_GIVEN; } String dollarsPart = ""; if (dollars > 0) { dollarsPart = convert(dollars) + " dollar" + (dollars == 1 ? "" : "s"); } String centsPart = ""; if (cents > 0) { if (dollarParts.length() > 0) { centsPart = " and "; } centsPart += convert(cents) + " cent" + (cents == 1 ? "" : "s"); } return dollarsPart + centsPart; }
Let’s test our code to make sure it works:
@Test public void whenGivenDollarsAndCents_thenReturnWords() { String expectedResult = "nine hundred twenty four dollars and sixty cents"; assertEquals( expectedResult, NumberWordConverter.getMoneyIntoWords(924.6)); } @Test public void whenTwoBillionDollarsGiven_thenReturnWords() { String expectedResult = "two billion one hundred thirty three million two hundred" + " forty seven thousand eight hundred ten dollars"; assertEquals( expectedResult, NumberWordConverter.getMoneyIntoWords(2_133_247_810)); } @Test public void whenThirtyMillionDollarsGiven_thenReturnWords() { String expectedResult = "thirty three million three hundred forty eight thousand nine hundred seventy eight dollars"; assertEquals( expectedResult, NumberWordConverter.getMoneyIntoWords(33_348_978)); }
Let’s also test some edge cases, and make sure we have covered them as well:
@Test public void whenZeroDollarsGiven_thenReturnEmptyString() { assertEquals("", NumberWordConverter.getMoneyIntoWords(0)); } @Test public void whenNoDollarsAndNineFiveNineCents_thenCorrectRounding() { assertEquals( "ninety six cents", NumberWordConverter.getMoneyIntoWords(0.959)); } @Test public void whenNoDollarsAndOneCent_thenReturnCentSingular() { assertEquals( "one cent", NumberWordConverter.getMoneyIntoWords(0.01)); }
3. Using a Library
Now that we’ve implemented our own algorithm, let’s do this conversion by using an existing library.
Tradukisto is a library for Java 8+, which can help us convert numbers to their word representations. First, we need to import it into our project (the latest version of this library can be found here):
<dependency> <groupId>pl.allegro.finance</groupId> <artifactId>tradukisto</artifactId> <version>1.0.1</version> </dependency>
We can now use MoneyConverters‘s asWords() method to do this conversion:
public String getMoneyIntoWords(String input) { MoneyConverters converter = MoneyConverters.ENGLISH_BANKING_MONEY_VALUE; return converter.asWords(new BigDecimal(input)); }
Let’s test this method with a simple test case:
@Test public void whenGivenDollarsAndCents_thenReturnWordsVersionTwo() { assertEquals( "three hundred ten £ 00/100", NumberWordConverter.getMoneyIntoWords("310")); }
We could also use the ICU4J library to do this, but it’s a large one and comes with many other features that are out of the scope of this article.
However, have a look at it if Unicode and globalization support is needed.
4. Conclusion
In this quick article, we saw two approaches on how to do the conversion of a sum of money into words.
The code for all the examples explained here, and much more can be found over on GitHub.