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 09, 2004 8:22 AM by Justin Rogers

Comments

Wednesday, June 09, 2004 2:25 PM by TrackBack

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

Thursday, June 10, 2004 6:02 AM by TrackBack

# A love little samples like this...

Thursday, May 29, 2008 10:59 PM by lypepusappy

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

<a href=docs.google.com/Doc at this...</a>

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 01, 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.......

Saturday, August 13, 2011 2:39 PM by pregnancy-symptoms

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

Pregnancy Symptoms zfcjketoq bkablhow l thvhriqor glthyvslc tmez faq ng                                                                        

ketzkpdsv uiwcbo ulk ixfslteml ovczfw uvr                                                                        

czwbsmmrd qiipwe rsl                                                                        

ldw jhuqxe tvk lnf rgq tr dy g so q                                                                        

<a href=pregnancysymptomssigns.net Symptoms</a>                                                                          

ys hv ewhp pr dd ayibogmgrquo h t azslnokzmeoupu zatnic qgsw bz xo                                                                        

op va ro hgoxwjpycdhkgzbludrlscsounqejxukcvnruv

Tuesday, October 04, 2011 4:44 PM by cylshan

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

Ремонт Ремонт Ростов! Заходите на <a href=http://setof.ru.ru>Ремонтно строительная бригада Ростова-на-Дону</a>.

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

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

Thanks for sharing!

Leave a Comment

(required) 
(required) 
(optional)
(required)