Currency To Words Convertor

The following code coverts numbers and/or currency values to proper English text. Converting currencies to proper text is useful for example when auto completing Cheques, Direct Debit mandates etc.

Please note: This software has no warranty (please see the disclaimer below for details). It is entirely your responsibility to ensure the output is correct.

The class has static methods for handling raw numbers, currencies stored as a long (ie in pence) and currencies stored as a BigDecimal (ie in pounds and pence).

By default this class uses Pounds and Pence as the currency names but methods are provided to allow these default values to be overridden.

License

This software is released under the GNU GPLv3 license

NumbersToWords

To use this class see the Usage section.

/**
 * Copyright (c) 2011 Keang Ltd
 *
 * The NumbersToWords class is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * The NumbersToWords class is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with the NumbersToWords class.  If not, see www.gnu.org/licenses.
 */

import java.math.BigDecimal;

/**
 * Converts integer numbers and currencies into written English text.
 * eg for numbers
 * 10123 = Ten Thousand One Hundred and Twenty Three
 * For currencies
 * 101.23 = One Hundred and One Pounds and Twenty Three Pence
 *
 * By default the class uses Pounds and Pence for currency names but methods are provided to
 * to allow other currencies to be constructed such as Dollars and Cents.
 *
 * The numbering system is based on the US system ie
 *
 * Number of Zeros	  Name
 * 	   2		 Hundred
 * 	   3		 Thousand
 * 	   6		 Million
 * 	   9		 Billion
 * 	  12		 Trillion
 * 	  15		 Quadrillion
 * 	  18		 Quintillion
 *
 *
 * @author A.G.Docherty
 * @version 1.0 - 27 Sep 2011
 */
public final class NumbersToWords
{
private static final String DFLT_POUNDS_PLURAL = "Pounds";
private static final String DFLT_POUNDS_SINGULAR = "Pound";
private static final String DFLT_PENCE_PLURAL = "Pence";
private static final String DFLT_PENCE_SINGULAR = "Pence";

private static final String WORD_ZERO = "Zero";
private static final String WORD_AND = "and";
private static final String WORD_ONLY = "Only";

/**
 * Converts the currency value in pounds and pence into words.
 *
 * The maximum value is Long.MAX_VALUE for the integer part of the currency
 * plus 99 for the decimal part, which equates to:
 * Nine Quintillion Two Hundred and Twenty Three Quadrillion Three Hundred and
 * Seventy Two Trillion Thirty Six Billion Eight Hundred and Fifty Four Million
 * Seven Hundred and Seventy Five Thousand Eight Hundred and Seven Pounds and
 * Ninety Nine Pence
 *
 * @param num the currency as a long (pence)
 * @return the words as an English sentence
 * @throws Exception
 */
public static String currencyToWords(BigDecimal num)
	{
	return currencyToWords(num, DFLT_POUNDS_PLURAL, DFLT_POUNDS_SINGULAR, DFLT_PENCE_PLURAL, DFLT_PENCE_SINGULAR);
	}

/**
 * Converts the currency value in pounds and pence into words.
 *
 * The maximum value is Long.MAX_VALUE for the integer part of the currency
 * plus 99 for the decimal part, which equates to:
 * Nine Quintillion Two Hundred and Twenty Three Quadrillion Three Hundred and
 * Seventy Two Trillion Thirty Six Billion Eight Hundred and Fifty Four Million
 * Seven Hundred and Seventy Five Thousand Eight Hundred and Seven Pounds and
 * Ninety Nine Pence
 *
 * @param num the currency as a long (pence)
 * @param intPlural the plural name of the integer part of the currency ie Pounds, Dollars, Euros etc
 * @param intSingular the singular name of the integer part of the currency ie Pound, Dollar, Euro etc
 * @param decPlural the plural name of the decimal part of the currency ie Pence, Cents etc
 * @param decSingular the singular name of the decimal part of the currency ie Pence, Cent etc
 * @return the words as an English sentence
 * @throws Exception
 */
public static String currencyToWords(BigDecimal num, String intPlural, String intSingular, String decPlural, String decSingular)
	{
	long pounds = num.longValue();

	BigDecimal p = num.subtract(new BigDecimal(pounds));
	p = p.movePointRight(2);

	return currencyToWords(pounds, p.longValueExact(), intPlural, intSingular, decPlural, decSingular);
	}
/**
 * Converts the currency value in pence into words.
 *
 * The maximum value is Long.MAX_VALUE which equates to:
 * Ninety Two Quadrillion Two Hundred and Thirty Three Trillion Seven Hundred and
 * Twenty Billion Three Hundred and Sixty Eight Million Five Hundred and
 * Forty Seven Thousand Seven Hundred and Fifty Eight Pounds and Seven Pence
 *
 * @param num the currency as a long (pence)
 * @return the words as an English sentence
 * @throws Exception
 */
public static String currencyToWords(long num)
	{
	return currencyToWords(num, DFLT_POUNDS_PLURAL, DFLT_POUNDS_SINGULAR, DFLT_PENCE_PLURAL, DFLT_PENCE_SINGULAR);
	}

/**
 * Converts the currency value in pence into words.
 * This method makes the assumption that the currencies words have plural and singular forms
 * if the word ends with an 's'.
 * For example 'Pounds' will be used as 'Two Pounds' or 'One Pound' whereas 'Pence' will be
 * 'Two Pence' or 'One Pence'
 *
 * The maximum value is Long.MAX_VALUE which equates to:
 * Ninety Two Quadrillion Two Hundred and Thirty Three Trillion Seven Hundred and
 * Twenty Billion Three Hundred and Sixty Eight Million Five Hundred and
 * Forty Seven Thousand Seven Hundred and Fifty Eight Pounds and Seven Pence
 *
 * @param num the currency as a long (pence)
 * @param intPlural the plural name of the integer part of the currency ie Pounds, Dollars, Euros etc
 * @param decPlural the plural name of the decimal part of the currency ie Pence, Cents etc
 * @return the words as an English sentence
 * @throws Exception
 */
public static String currencyToWords(long num, String intPlural, String decPlural)
	{
	String intSing;
	String decSing;

	if ( intPlural.endsWith("s") )
		intSing = intPlural.substring(0, intPlural.length()-1);
	else
		intSing = intPlural;

	if ( decPlural.endsWith("s") )
		decSing = decPlural.substring(0, decPlural.length()-1);
	else
		decSing = decPlural;

	return currencyToWords(num, intPlural, intSing, decPlural, decSing);
	}

/**
 * Converts the currency value in pence into words.
 *
 * The maximum value is Long.MAX_VALUE which equates to:
 * Ninety Two Quadrillion Two Hundred and Thirty Three Trillion Seven Hundred and
 * Twenty Billion Three Hundred and Sixty Eight Million Five Hundred and
 * Forty Seven Thousand Seven Hundred and Fifty Eight Pounds and Seven Pence
 *
 * @param num the currency as a long (pence)
 * @param intPlural the plural name of the integer part of the currency ie Pounds, Dollars, Euros etc
 * @param intSingular the singular name of the integer part of the currency ie Pound, Dollar, Euro etc
 * @param decPlural the plural name of the decimal part of the currency ie Pence, Cents etc
 * @param decSingular the singular name of the decimal part of the currency ie Pence, Cent etc
 * @return the words as an English sentence
 * @throws Exception
 */
public static String currencyToWords(long num, String intPlural, String intSingular, String decPlural, String decSingular)
	{
	if ( num < 0 )
		throw new IllegalArgumentException("Negative numbers can not be converted");

	long pence = num % 100;
	long pounds = num / 100;

	return currencyToWords(pounds, pence, intPlural, intSingular, decPlural, decSingular);
	}

/**
 * Converts the currency value in pence into words.
 *
 * The maximum value is Long.MAX_VALUE which equates to:
 * Ninety Two Quadrillion Two Hundred and Thirty Three Trillion Seven Hundred and
 * Twenty Billion Three Hundred and Sixty Eight Million Five Hundred and
 * Forty Seven Thousand Seven Hundred and Fifty Eight Pounds and Seven Pence
 *
 * @param num the currency as a long (pence)
 * @param intPlural the plural name of the integer part of the currency ie Pounds, Dollars, Euros etc
 * @param intSingular the singular name of the integer part of the currency ie Pound, Dollar, Euro etc
 * @param decPlural the plural name of the decimal part of the currency ie Pence, Cents etc
 * @param decSingular the singular name of the decimal part of the currency ie Pence, Cent etc
 * @return the words as an English sentence
 * @throws Exception
 */
private static String currencyToWords(long pounds, long pence, String intPlural, String intSingular, String decPlural, String decSingular)
	{
	if ( pounds < 0 || pence < 0 )
		throw new IllegalArgumentException("Negative numbers can not be converted");

	StringBuilder str = new StringBuilder();
	NumbersToWords n = new NumbersToWords();

	if ( pounds == 0 && pence == 0 )
		{
		str.append(WORD_ZERO);
		str.append(" ");
		str.append(intPlural);
		}

	if ( pounds > 0 )
		{
		str.append(n.numAsText(pounds));
		str.append(" ");

		if ( pounds == 1 )
			str.append(intSingular);
		else
			str.append(intPlural);

		if ( pence == 0 )
			{
			str.append(" ");
			str.append(WORD_ONLY);
			}
		else
			{
			str.append(" ");
			str.append(WORD_AND);
			str.append(" ");
			}
		}

	if ( pence > 0 )
		{
		str.append(n.numAsText(pence));
		str.append(" ");

		if ( pence == 1 )
			str.append(decSingular);
		else
			str.append(decPlural);
		}

	return str.toString();
	}

/**
 * Converts the numeric value into words.
 * The maximum value is Long.MAX_VALUE which equates to:
 * Nine Quintillion Two Hundred and Twenty Three Quadrillion Three Hundred and
 * Seventy Two Trillion Thirty Six Billion Eight Hundred and Fifty Four Million
 * Seven Hundred and Seventy Five Thousand Eight Hundred and Seven
 *
 * @param num the number
 * @return the words
 * @throws Exception
 */
public static String toWords(long num)
	{
	// Defining variables q is quotient, r is remainder
	NumbersToWords n = new NumbersToWords();
	return n.numAsText(num);
	}

private final String[] oneToTwenty = { "", "One", "Two", "Three", "Four", "Five", "Six",
        "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
        "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen",
        "Nineteen" };
private final String[] tens = { "", "Ten", "Twenty", "Thirty", "Forty", "Fifty",
        "Sixty", "Seventy", "Eighty", "Ninety" };
private final String[] scaleNames = { "", "Hundred", "Thousand", "Million", "Billion", "Trillion", "Quadrillion", "Quintillion" };

/**
 * A private constructor to restrict access to the static methods
 */
private NumbersToWords()
	{
	// do nothing
	}

/**
 * Gets this number as text.
 *
 * @param num the number
 * @return the textual representation of this number in English
 */
private String numAsText(long num)
	{
	int len;
	StringBuilder str = new StringBuilder();

	if ( num < 0 )
		throw new IllegalArgumentException("Negative numbers can not be converted");

	if ( num == 0 )
		str.append(WORD_ZERO);

	boolean first = true;

	while ( num > 0 )
		{
		if ( !first )
			str.append(" ");

		len = numberCount(num);

		if ( len < 3 )
			{
			// handle 1 and 2 digit numbers
			if ( str.length() > 0 )
				{
				str.append(WORD_AND);
				str.append(" ");
				}

			if ( num < 20 )
				str.append(oneToTwenty[(int)num]);
			else
				twoDigitsToWords((int)num, str);

			num = 0;
			}
		else if ( len == 3 )
			{
			// handle 3 digit numbers
			threeDigitsToWords((int)num, str);
			num = 0;
			}
		else
			{
			// handle all other numbers

			// get the scale
			int f = (len + 2)/3;
			f--;

			if ( f >= scaleNames.length-1 )
				throw new IllegalArgumentException("The number "+num+" is too large");

			long div = 1000;

			// calc the scaling number to divide by
			for ( int i = 1; i < f; i++ )
                {
                div *= 1000;
                }

			int q = (int)(num / div);
			long r = (num % div);

			if ( len % 3 == 0 )
				threeDigitsToWords(q, str);
			else
				twoDigitsToWords(q, str);

			str.append(" ");
			str.append(scaleNames[f+1]);
			num = r;
			}

		first = false;
		}

	return str.toString();
	}

/**
 * Counts the number of digits in the input number
 *
 * @param num  the number
 * @return the number of digits
 */
private int numberCount(long num)
	{
	int count = 0;

	while ( num > 0 )
		{
		count++;
		num = num / 10;
		}

	return count;
	}

/**
 * Converts a two digit number to words
 *
 * @param num the number
 * @param str
 * @return the words
 */
private void twoDigitsToWords(int num, StringBuilder str)
	{
	if ( num < 20 )
		{
		str.append(oneToTwenty[num]);
		}
	else
		{
		int q = num / 10;
		int r = num % 10;

		str.append(tens[q]);

		if ( r > 0 )
			{
			str.append(" ");
			str.append(oneToTwenty[r]);
			}
		}
	}

/**
 * Converts a three digit number to words
 *
 * @param num the number
 * @param str
 * @return the words
 */
private void threeDigitsToWords(int num, StringBuilder str)
	{
	int q = num / 100;
	int r = num % 100;

	str.append(oneToTwenty[q]);
	str.append(" ");
	str.append(scaleNames[1]);

	if ( r > 0 )
		{
		str.append(" ");
		str.append(WORD_AND);
		str.append(" ");
		twoDigitsToWords(r, str);
		}
	}
}

    

Usage

The following code is an example of how to convert some values to text.
    // Raw Numbers
    // sets text to 'One Thousand and One'
    text = NumbersToWords.toWords(1001);

    // sets text to 'Nine Thousand Nine Hundred and Ninety Nine'
    text = NumbersToWords.toWords(9999);

    // sets text to 'Five Hundred Million'
    text = NumbersToWords.toWords(500000000);

    // sets text to 'Nine Quintillion Two Hundred and Twenty Three Quadrillion Three Hundred
    //  and Seventy Two Trillion Thirty Six Billion Eight Hundred and Fifty Four Million
    //  Seven Hundred and Seventy Five Thousand Eight Hundred and Seven'
    text = NumbersToWords.toWords(9223372036854775807L);


    // Currencies using long
    // sets text to 'Nineteen Pence'
    text = NumbersToWords.currencyToWords(19);

    // sets text to 'Two Pounds and Two Pence'
    text = NumbersToWords.currencyToWords(202);

    // sets text to 'Four Hundred and Forty Four Pounds and Forty Four Pence'
    text = NumbersToWords.currencyToWords(44444);

    // sets text to 'One Dollar and Eleven Cents'
    text = NumbersToWords.currencyToWords(111, "Dollars", "Cents");


    // Currencies using BigDecimal
    // sets text to 'Nineteen Pence'
    text = NumbersToWords.currencyToWords(new BigDecimal("0.19"));

    // sets text to 'Two Pounds and Two Pence'
    text = NumbersToWords.currencyToWords(new BigDecimal("2.02"));

    // sets text to 'Four Hundred and Forty Four Pounds and Forty Four Pence'
    text = NumbersToWords.currencyToWords(new BigDecimal("444.44"));