.NET convert number to string representation (1 to one, 2 to two, etc...)

Is there a built in method in .NET to convert a number to the string representation of the number? For example, 1 becomes one, 2 becomes two, etc.


Solution 1:

I've always been a fan of the recursive method

  public static string NumberToText( int n)
  {
   if ( n < 0 )
      return "Minus " + NumberToText(-n);
   else if ( n == 0 )
      return "";
   else if ( n <= 19 )
      return new string[] {"One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", 
         "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", 
         "Seventeen", "Eighteen", "Nineteen"}[n-1] + " ";
   else if ( n <= 99 )
      return new string[] {"Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", 
         "Eighty", "Ninety"}[n / 10 - 2] + " " + NumberToText(n % 10);
   else if ( n <= 199 )
      return "One Hundred " + NumberToText(n % 100);
   else if ( n <= 999 )
      return NumberToText(n / 100) + "Hundreds " + NumberToText(n % 100);
   else if ( n <= 1999 )
      return "One Thousand " + NumberToText(n % 1000);
   else if ( n <= 999999 )
      return NumberToText(n / 1000) + "Thousands " + NumberToText(n % 1000);
   else if ( n <= 1999999 )
      return "One Million " + NumberToText(n % 1000000);
   else if ( n <= 999999999)
      return NumberToText(n / 1000000) + "Millions " + NumberToText(n % 1000000);
   else if ( n <= 1999999999 )
      return "One Billion " + NumberToText(n % 1000000000);
   else 
      return NumberToText(n / 1000000000) + "Billions " + NumberToText(n % 1000000000);
}

Source

Solution 2:

Ah, there may not be a class to do this, but there was a code golf question which I provided a C# example for:

Code Golf: Number to Words

However, it's not the easiest to read and it only goes up to decimal.MaxValue, so I've written a new version that will go as high as you need to.

I couldn't find any information regarding values higher than vigintillions, but if you append the values to the thou[] array, you can continue going up as far as you like. It still doesn't support fractions, but I'm thinking about adding that at some point.

    static string NumericStringToWords(string NumericValue)
    {
        if ("0" == NumericValue) return "zero";

        string[] units = { "one", "two", "three", "four", "five", 
                           "six", "seven", "eight", "nine" };

        string[] teens = { "eleven", "twelve", "thirteen", "four", "fifteen", 
                           "sixteen", "seventeen", "eighteen", "nineteen" };

        string[] tens = { "ten", "twenty", "thirty", "forty", "fifty", 
                          "sixty", "seventy", "eighty", "ninety" };

        string[] thou = { "thousand", "million", "billion", "trillion", 
                          "quadrillion", "quintillion", "sextillion", 
                          "septillion", "octillion", "nonillion", "decillion", 
                          "udecillion", "duodecillion", "tredecillion", 
                          "quattuordecillion", "quindecillion", "sexdecillion", 
                          "septendecillion", "octodecillion", "novemdecillion", 
                          "vigintillion" };

        string sign = String.Empty;
        if ("-" == NumericValue.Substring(0, 1))
        {
            sign = "minus ";
            NumericValue = NumericValue.Substring(1);
        }

        int maxLen = thou.Length * 3;
        int actLen = NumericValue.Length;
        if(actLen > maxLen)
            throw new InvalidCastException(String.Format("{0} digit number specified exceeds the maximum length of {1} digits.  To evaluate this number, you must first expand the thou[] array.", actLen, maxLen));

        //Make sure that the value passed in is indeed numeric... we parse the entire string
        //rather than just cast to a numeric type to allow us to handle large number types passed
        //in as a string.  Otherwise, we're limited to the standard data type sizes.
        int n; //We don't care about n, but int.TryParse requires it
        if (!NumericValue.All(c => int.TryParse(c.ToString(), out n)))
            throw new InvalidCastException();

        string fraction = String.Empty;
        if (NumericValue.Contains("."))
        {
            string[] split = NumericValue.Split('.');
            NumericValue = split[0];
            fraction = split[1];
        }

        StringBuilder word = new StringBuilder();
        ulong loopCount = 0;

        while (0 < NumericValue.Length)
        {
            int startPos = Math.Max(0, NumericValue.Length - 3);
            string crntBlock = NumericValue.Substring(startPos);
            if (0 < crntBlock.Length)
            {
                //Grab the hundreds tens & units for the current block
                int h = crntBlock.Length > 2 ? int.Parse(crntBlock[crntBlock.Length - 3].ToString()) : 0;
                int t = crntBlock.Length > 1 ? int.Parse(crntBlock[crntBlock.Length - 2].ToString()) : 0;
                int u = crntBlock.Length > 0 ? int.Parse(crntBlock[crntBlock.Length - 1].ToString()) : 0;

                StringBuilder thisBlock = new StringBuilder();

                if (0 < u)
                    thisBlock.Append(1 == t? teens[u - 1] : units[u - 1]);

                if (1 != t)
                {
                    if (1 < t && 0 < u) thisBlock.Insert(0, "-");
                    if (0 < t) thisBlock.Insert(0, tens[t - 1]);
                }

                if (0 < h)
                {
                    if (t > 0 | u > 0) thisBlock.Insert(0, " and ");
                    thisBlock.Insert(0, String.Format("{0} hundred", units[h - 1]));
                }

                //Check to see if we've got any data left and add
                //appropriate word separator ("and" or ",")
                bool MoreLeft = 3 < NumericValue.Length;
                if (MoreLeft && (0 == h) && (0 == loopCount))
                    thisBlock.Insert(0, " and ");
                else if (MoreLeft)
                    thisBlock.Insert(0, String.Format(" {0}, ", thou[loopCount]));

                word.Insert(0, thisBlock);
            }

            //Remove the block we just evaluated from the 
            //input string for the next loop
            NumericValue = NumericValue.Substring(0, startPos);

            loopCount++;
        }
        return word.Insert(0, sign).ToString();
    }

I tested it using Decimal.MaxValue appended to itself to generate a large number of:

seven octodecillion, nine hundred and twenty-two septendecillion, eight hundred and sixteen sexdecillion, two hundred and fifty-one quindecillion, four hundred and twenty-six quattuordecillion, four hundred and thirty-three tredecillion, seven hundred and fifty-nine duodecillion, three hundred and fifty-four udecillion, three hundred and ninety-five decillion, thirty-three nonillion, five hundred and seventy-nine octillion, two hundred and twenty-eight septillion, one hundred and sixty-two sextillion, five hundred and four quintillion, two hundred and sixty-four quadrillion, three hundred and thirty-seven trillion, five hundred and ninety-three billion, five hundred and forty-three million, nine hundred and fifty- thousand, three hundred and thirty-five