Code-Only: int/long/double conversion to Spoken Numerics

/*
    The below program works pretty well, but there are some
    round-off precision errors in the double that are giving
    me hell.  I may or may not look into it.  Ideally, if
    given a string, I'd parse the string.  If given a number,
    then and only then would I parse the number.  Since the
    string representation of a double is quite relaxed, it
    would actually be easier to parse.
*/

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", "Fourty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"
        };
    private static string[] groupMapping =
        new string[] {
            "Hundred", "Thousand", "Million", "Billion", "Trillion", "Quadrillion", "Quintillion", "Sextillian",
            "Septillion", "Octillion", "Nonillion", "Decillion", "Undecillion", "Duodecillion", "Tredecillion",
            "Quattuordecillion", "Quindecillion", "Sexdecillion", "Septendecillion", "Octodecillion", "Novemdecillion",
            "Vigintillion", "Unvigintillion", "Duovigintillion", "10^72", "10^75", "10^78", "10^81", "10^84", "10^87",
            "Vigintinonillion", "10^93", "10^96", "Duotrigintillion", "Trestrigintillion"
        };
       
        // NOTE: 10^303 is approaching the limits of double, as ~1.7e308 is where we are going
        // 10^303 is a centillion and a 10^309 is a duocentillion
       
    private static void Main(string[] args) {
        double valToParse = double.Parse(args[0]);
        Console.WriteLine(EnglishFromNumber(valToParse));
    }
   
   
    private static string EnglishFromNumber(int number) {
        return EnglishFromNumber((long) number);
    }

    private static string EnglishFromNumber(long number) {
        return EnglishFromNumber((double) number);
    }

    private static string EnglishFromNumber(double number) {
        string sign = null;
        if ( number < 0 ) {
            sign = "Negative";
            number = Math.Abs(number);
        }

        int decimalDigits = 0;
        Console.WriteLine(number);
        while(number < 1 || (number - Math.Floor(number) > 1e-10)) {
            number *= 10;
            decimalDigits++;
        }
        Console.WriteLine("Total Decimal Digits: {0}", decimalDigits);
       
        string decimalString = null;
        while(decimalDigits-- > 0) {
            int digit = (int) (number % 10); number /= 10;
            decimalString = onesMapping[digit] + " " + decimalString;
        }

        string retVal = null;
        int group = 0;
        if ( number < 1 ) {
            retVal = onesMapping[0];
        } else {
            while(number >= 1) {
                int numberToProcess = (number >= 1e16) ? 0 : (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 String.Format("{0}{4}{1}{3}{2}",
            sign,
            retVal,
            decimalString,
            (decimalString != null) ? " Point " : "",
            (sign != null) ? " " : "");
    }
   
    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 8:22 AM by Justin Rogers

Comments

Wednesday, February 18, 2009 7:47 AM by Chu

# re: Code-Only: int/long/double conversion to Spoken Numerics

How about from integer to sound.

Wednesday, August 19, 2009 6:16 PM by Spreety

# re: Code-Only: int/long/double conversion to Spoken Numerics

Cool class. As a minor detail, a zero appears to cause an infinite loop.

To fix, added a few lines:

   public static string EnglishFromNumber(double number)

   {

       string sign = null;

       if (number == 0)

       {

           return "Zero";

       }

       if (number < 0)

       {

           sign = "Negative";

           number = Math.Abs(number);

       }

Monday, December 21, 2009 11:57 AM by KD

# re: Code-Only: int/long/double conversion to Spoken Numerics

Hi Justin,

The function and code snipped is cool one

Try 67621.694 and 67621.695 and see result

Is it rounding problems?

Monday, August 23, 2010 11:56 PM by Michael Ray

# re: Code-Only: int/long/double conversion to Spoken Numerics

Good post.  I like the results.

Tuesday, October 26, 2010 5:25 AM by sdfmvb

# re: Code-Only: int/long/double conversion to Spoken Numerics

Продам  Добрый Вечер ! А ВВБГ КОГ-1 П ПЭП-В-100 ТГ

Friday, October 29, 2010 10:55 AM by Sara Smith

# re: Code-Only: int/long/double conversion to Spoken Numerics

We work with all of the apartments for rent in north austin.

Monday, November 1, 2010 11:30 AM by فيس بوك

# re: Code-Only: int/long/double conversion to Spoken Numerics

very helpful tutorial thanks

Wednesday, May 18, 2011 1:16 AM by Keylogger

# re: Code-Only: int/long/double conversion to Spoken Numerics

Thanks for the nice info

Monday, May 23, 2011 7:08 AM by Keylogger

# re: Code-Only: int/long/double conversion to Spoken Numerics

Thanks for the nice information.......

Thursday, October 6, 2011 5:00 AM by Repair Zip

# re: Code-Only: int/long/double conversion to Spoken Numerics

Thanks for sharing!

Friday, May 25, 2012 8:30 PM by matt

# re: Code-Only: int/long/double conversion to Spoken Numerics

Thanks so much. It's very useful for me.

Sunday, August 5, 2012 4:04 PM by Dexter Wright

# re: Code-Only: int/long/double conversion to Spoken Numerics

Fantastic snippet Justin! I think you can fix your "rounding" problems in about five minutes by simply changing your variable, "number", from a double to a decimal type, (and append an 'm' after literal assignments. You can't use double since some values simply don't exist for that type - cannot be represented in that type. Again, great job!

Saturday, October 6, 2012 12:30 PM by Whalen

# re: Code-Only: int/long/double conversion to Spoken Numerics

I was curious if you ever thought of changing the structure of your blog?

Its very well written; I love what youve got to say. But maybe you could a little more in

the way of content so people could connect with it better.

Youve got an awful lot of text for only having one or two pictures.

Maybe you could space it out better?

Monday, October 8, 2012 12:22 PM by Pearsall

# re: Code-Only: int/long/double conversion to Spoken Numerics

Woah! I'm really loving the template/theme of this blog. It's simple, yet effective.

A lot of times it's challenging to get that "perfect balance" between superb usability and visual appeal. I must say you have done a amazing job with this. Also, the blog loads extremely fast for me on Firefox. Exceptional Blog!

Thursday, October 11, 2012 7:44 AM by Horse shippers

# re: Code-Only: int/long/double conversion to Spoken Numerics

The codes you’ve posted are really useful and have made my task easier. I really appreciate the work you’re doing by way of these blogs.

Wednesday, October 17, 2012 3:05 AM by purchase cheap cheap wow gold

# re: Code-Only: int/long/double conversion to Spoken Numerics

Keep functioning ,splendid job!

Tuesday, January 8, 2013 4:12 AM by Estevez

# re: Code-Only: int/long/double conversion to Spoken Numerics

Saved as a favorite, I really like your site!