A conversion from integer to long form english... I could write that ;-)

[Editorial note: A more complete sample is available through article: http://weblogs.asp.net/justin_rogers/articles/151757.aspx]

I find little conversion functions to be the most interesting type of programming you can spend your time on.  You wind up exercising so many areas of programming expertise to make the algorithms short, complete, bug free, and as fast as possible.  While this next algorithm fits a couple of those, I have to admit I'm quite tired and I only spent about 20 minutes working the solution.  It would be interesting to extend the algorithm to work with decimals, possibly units of measure, etc...

using System;

public class NumberToEnglish {
    private static string[] onesMapping =
        new string[] {
            "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine",
            "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"
        };
    private static string[] tensMapping =
        new string[] {
            "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"
        };
    private static string[] groupMapping =
        new string[] {
            "Hundred", "Thousand", "Million", "Billion", "Trillion"
        };
       
    private static void Main(string[] args) {
        Console.WriteLine(EnglishFromNumber(long.Parse(args[0])));
    }
   
    private static string EnglishFromNumber(int number) {
        return EnglishFromNumber((long) number);
    }

    private static string EnglishFromNumber(long number) {
        if ( number == 0 ) {
            return onesMapping[number];
        }
       
        string sign = "Positive";
        if ( number < 0 ) {
            sign = "Negative";
            number = Math.Abs(number);
        }
       
        string retVal = null;
        int group = 0;
        while(number > 0) {
            int numberToProcess = (int) (number % 1000);
            number = number / 1000;
           
            string groupDescription = ProcessGroup(numberToProcess);
            if ( groupDescription != null ) {
                if ( group > 0 ) {
                    retVal = groupMapping[group] + " " + retVal;
                }
                retVal = groupDescription + " " + retVal;
            }
           
            group++;
        }
       
        return sign + " " + retVal;
    }
   
    private static string ProcessGroup(int number) {
        int tens = number % 100;
        int hundreds = number / 100;
       
        string retVal = null;
        if ( hundreds > 0 ) {
            retVal = onesMapping[hundreds] + " " + groupMapping[0];
        }
        if ( tens > 0 ) {
            if ( tens < 20 ) {
                retVal += ((retVal != null) ? " " : "") + onesMapping[tens];
            } else {
                int ones = tens % 10;
                tens = (tens / 10) - 2; // 20's offset
               
                retVal += ((retVal != null) ? " " : "") + tensMapping[tens];
               
                if ( ones > 0 ) {
                    retVal += ((retVal != null) ? " " : "") + onesMapping[ones];
                }
            }
        }
       
        return retVal;
    }
}

Published Wednesday, June 9, 2004 6:37 AM by Justin Rogers
Filed under:

Comments

Wednesday, June 9, 2004 10:00 AM by kvr

# re: A conversion from integer to long form english... I could write that ;-)

Shouldn't Fourty be spelled as Forty?
Wednesday, June 9, 2004 5:59 PM by AT

# re: A conversion from integer to long form english... I could write that ;-)

How about to convert them in both ways ?
English -> number ?
Wednesday, June 9, 2004 11:37 PM by Justin Rogers

# re: A conversion from integer to long form english... I could write that ;-)

Converting back would require some math that is extremely lossy. If I were going to go backwards, I would consider the use of a large number library. Since the only publicly available one for .NET isn't that great, and I don't feel like releasing and supporting my own, I'll leave the conversion from English -> number as an exercise for someone else.

Thursday, June 10, 2004 12:05 PM by Sean Lynch

# Converting from english to number

I just used a bunch of case statments.
Thursday, June 10, 2004 12:41 PM by Andy Smith

# re: A conversion from integer to long form english... I could write that ;-)

I did it in 7 less lines of code...
Thursday, June 10, 2004 6:45 PM by Stuart Hallows

# re: A conversion from integer to long form english... I could write that ;-)

Twenty minutes? Pah! I knocked one out in ten.
BOSH.
Thursday, June 10, 2004 8:25 PM by Justin Rogers

# re: A conversion from integer to long form english... I could write that ;-)

You people should post linkies so we can see your code. Hopefully you followed the article link which also handles numbers up to some astronomical double number, and converts values after the decimal point as well.

Friday, June 11, 2004 8:29 AM by Ford

# TestCase

EnglishFromNumber(Int64.MinValue)

I would like to say: Math.Abs is evil.
Friday, June 11, 2004 10:09 AM by Justin Rogers

# re: A conversion from integer to long form english... I could write that ;-)

Yes, the version that uses Double should fix some of that. Follow the article link and if you have the same problem. I could possibly see a round-off error for Int64 even when using double as the base number type.
Monday, October 15, 2007 8:01 AM by Karan

# re: A conversion from integer to long form english... I could write that ;-)

Hi

Is it possible to convert the integer into Ordinal text numbering like First, Second, Third.

Thursday, August 14, 2008 6:36 PM by Kevwe

# re: A conversion from integer to long form english... I could write that ;-)

Is it possible to add 'AND' in the results. Like 'One Hundred AND Fifty' for '150'?

Tuesday, February 24, 2009 4:20 AM by Ozein

# re: A conversion from integer to long form english... I could write that ;-)

you are converting only integers or long data type, but in fact this procedure needs to handle decimal or floats since its mainly used for only statements in invoices or checks.