2

I am trying to make a program that's changing number to words, I know it exist and answered by Converting numbers in to words

but what I am trying to do is for example I have a input 114321 the program goes into a loop processing first the 321 to three hundred twenty one then the 114 but with a prefix of thousand one hundred fourteen thousand so the overall output is like one hundred fourteen thousand three hundred twenty one. I tried it like this but its wrong and im not even close

public static string NumberToWords(int number)
    {
        var unitsMap = new[] { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
        var tensMap = new[] { "zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };
        var hundredsMap = new[] { "", "Thousand", "Million" };
        string words = "";
        string snumber = number.ToString();
        int tempInt = number;
        int counter;

        for (counter = 0;counter <= (snumber.Length/3); counter++)
        {
            if (snumber.Length > 3)
            {
                tempInt = Convert.ToInt32(snumber.Substring(snumber.Length - 3));
            }

            if ((tempInt / 100) > 0)
            {
                words += NumberToWords(tempInt / 100) + " hundred ";
                tempInt %= 100;
            }

            if (tempInt != 0)
            {
                if (tempInt < 20)
                {
                    words += unitsMap[tempInt];
                }
                else
                {
                    words += tensMap[tempInt / 10];
                    if ((tempInt % 10) > 0)
                    {
                        words += " " + unitsMap[tempInt % 10];
                    }
                }
            }
            words += hundredsMap[counter];             
        }
        return words;
    }
Community
  • 1
  • 1
Vian Ojeda Garcia
  • 827
  • 4
  • 17
  • 34
  • 2
    Can you explain why the linked answer isn't suitable? Otherwise, please show us what it's outputing, what it *should* be outputing, and what you've attempted so far. – Rob May 02 '17 at 23:25
  • " I have a input 114321 the program goes into a loop processing first the 321 then the 114 but with a prefix of thousand." Please rephrase this sentence. Its very unclear what you mean. –  May 02 '17 at 23:31
  • @Rob Im just thinking if there is any possible way. The output should be `one hundred fourteen thousand three hundred twenty one` my output is `three hundred twenty one one hundred fourteen thousand` – Vian Ojeda Garcia May 02 '17 at 23:36
  • @Amy there you go. Please read my edit – Vian Ojeda Garcia May 02 '17 at 23:37
  • Excellent edit, that's much clearer now. –  May 02 '17 at 23:38
  • What is the link you posted to NOT doing as you describe. LukeH's answer appears to do just what you are asking. – JohnG May 02 '17 at 23:40
  • @JohnG I did not say that it is wrong. Im just thinking if there is other way to do it. – Vian Ojeda Garcia May 02 '17 at 23:41
  • Did you debug thru the code and check why it is processing the number other way around ? – Chetan May 03 '17 at 01:29
  • @ChetanRanpariya yep. Because It process first the `321` If I proccess the thousand first it will display ok. But I can't figure how to determine the suffix eg `thousand,million` – Vian Ojeda Garcia May 03 '17 at 01:56

2 Answers2

1

The main trick to fix your code with minimal changes is that you should build string for each group separately in right to left order and then add them into a string in left to right order. In this way you can also deal with the need of additional spaces relatively easily (I mean when you have "1000300" you get `one_million_three_hundreds" with single space between all words despite the fact that the whole "thousands" group is missing).

    public static string NumberToWords(int number)
    {
        if (number == 0)
            return "zero";

        var unitsMap = new[] { "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
        var tensMap = new[] { "", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };
        var hundredsMap = new[] { "", " Thousand", " Million" };

        string fullString = "";
        bool negative = (number < 0);
        int rest = Math.Abs(number);


        for (int counter = 0; rest > 0; counter++)
        {
            string groupWords = "";
            int currentGroup = rest % 1000;
            rest /= 1000;

            int hundreds = currentGroup / 100;
            if (hundreds > 0)
            {
                groupWords += unitsMap[hundreds] + " hundred";
                currentGroup %= 100;
            }

            if (currentGroup != 0)
            {
                if (groupWords.Length > 0)
                    groupWords += " ";
                if (currentGroup < 20)
                {
                    groupWords += unitsMap[currentGroup];
                }
                else
                {
                    groupWords += tensMap[currentGroup / 10];
                    if ((currentGroup % 10) > 0)
                    {
                        groupWords += " " + unitsMap[currentGroup % 10];
                    }
                }
            }

            // handle case such as just "one million"
            if (groupWords.Length > 0)
            {
                groupWords += hundredsMap[counter];
                // handle case such as just "one million"
                if (fullString.Length == 0)
                    fullString = groupWords;
                else
                    fullString = groupWords + " " + fullString;
            }
        }
        return negative ? "minus " + fullString : fullString;
    }

Also note that you don't really need snumber at all (not to mention a bug in its usage where you always got last 3 digits for each and every group)

SergGr
  • 23,570
  • 2
  • 30
  • 51
1

You can use the following console application code as a reference to achieve your results. The code will accepts a monetary value in numbers up to 2 decimals and prints it in English.

namespace ConsoleApplication2
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text.RegularExpressions;
    class Program
    {
       static void Main(string[] args)
        {
            bool repeat = true;
            while (repeat)
            {
                string inputMonetaryValueInNumberic = string.Empty;
                string centPart = string.Empty;
                string dollarPart = string.Empty;
                Console.Write("\nEnter the monetary value : ");
                inputMonetaryValueInNumberic = Console.ReadLine();
                inputMonetaryValueInNumberic = inputMonetaryValueInNumberic.TrimStart('0');

                if (ValidateInput(inputMonetaryValueInNumberic))
                {

                    if (inputMonetaryValueInNumberic.Contains('.'))
                    {
                        centPart = ProcessCents(inputMonetaryValueInNumberic.Substring(inputMonetaryValueInNumberic.IndexOf(".") + 1));
                        dollarPart = ProcessDollar(inputMonetaryValueInNumberic.Substring(0, inputMonetaryValueInNumberic.IndexOf(".")));
                    }
                    else
                    {
                        dollarPart = ProcessDollar(inputMonetaryValueInNumberic);
                    }
                    centPart = string.IsNullOrWhiteSpace(centPart) ? string.Empty : " and " + centPart;
                    Console.WriteLine(string.Format("\n\n{0}{1}", dollarPart, centPart));
                }
                else
                {
                    Console.WriteLine("Invalid Input..");
                }

                Console.WriteLine("\n\nPress any key to continue or Escape of close : ");
                var loop = Console.ReadKey();
                repeat = !loop.Key.ToString().Contains("Escape");
                Console.Clear();
            }

        }

        private static string ProcessCents(string cents)
        {
            string english = string.Empty;
            string dig3 = Process3Digit(cents);
            if (!string.IsNullOrWhiteSpace(dig3))
            {
                dig3 = string.Format("{0} {1}", dig3, GetSections(0));
            }
            english = dig3 + english;
            return english;
        }
        private static string ProcessDollar(string dollar)
        {
            string english = string.Empty;
            foreach (var item in Get3DigitList(dollar))
            {
                string dig3 = Process3Digit(item.Value);
                if (!string.IsNullOrWhiteSpace(dig3))
                {
                    dig3 = string.Format("{0} {1}", dig3, GetSections(item.Key));
                }
                english = dig3 + english;
            }
            return english;
        }
        private static string Process3Digit(string digit3)
        {
            string result = string.Empty;
            if (Convert.ToInt32(digit3) != 0)
            {
                int place = 0;
                Stack<string> monetaryValue = new Stack<string>();
                for (int i = digit3.Length - 1; i >= 0; i--)
                {
                    place += 1;
                    string stringValue = string.Empty;
                    switch (place)
                    {
                        case 1:
                            stringValue = GetOnes(digit3[i].ToString());
                            break;
                        case 2:
                            int tens = Convert.ToInt32(digit3[i]);
                            if (tens == 1)
                            {
                                if (monetaryValue.Count > 0)
                                {
                                    monetaryValue.Pop();
                                }
                                stringValue = GetTens((digit3[i].ToString() + digit3[i + 1].ToString()));
                            }
                            else
                            {
                                stringValue = GetTens(digit3[i].ToString());
                            }
                            break;
                        case 3:
                            stringValue = GetOnes(digit3[i].ToString());
                            if (!string.IsNullOrWhiteSpace(stringValue))
                            {
                                string postFixWith = " Hundred";
                                if (monetaryValue.Count > 0)
                                {
                                    postFixWith = postFixWith + " And";
                                }
                                stringValue += postFixWith;
                            }
                            break;
                    }
                    if (!string.IsNullOrWhiteSpace(stringValue))
                        monetaryValue.Push(stringValue);
                }
                while (monetaryValue.Count > 0)
                {
                    result += " " + monetaryValue.Pop().ToString().Trim();
                }
            }
            return result;
        }
        private static Dictionary<int, string> Get3DigitList(string monetaryValueInNumberic)
        {
            Dictionary<int, string> hundredsStack = new Dictionary<int, string>();
            int counter = 0;
            while (monetaryValueInNumberic.Length >= 3)
            {
                string digit3 = monetaryValueInNumberic.Substring(monetaryValueInNumberic.Length - 3, 3);
                monetaryValueInNumberic = monetaryValueInNumberic.Substring(0, monetaryValueInNumberic.Length - 3);
                hundredsStack.Add(++counter, digit3);
            }
            if (monetaryValueInNumberic.Length != 0)
                hundredsStack.Add(++counter, monetaryValueInNumberic);
            return hundredsStack;
        }
        private static string GetTens(string tensPlaceValue)
        {
            string englishEquvalent = string.Empty;
            int value = Convert.ToInt32(tensPlaceValue);
            Dictionary<int, string> tens = new Dictionary<int, string>();
            tens.Add(2, "Twenty");
            tens.Add(3, "Thirty");
            tens.Add(4, "Forty");
            tens.Add(5, "Fifty");
            tens.Add(6, "Sixty");
            tens.Add(7, "Seventy");
            tens.Add(8, "Eighty");
            tens.Add(9, "Ninty");
            tens.Add(10, "Ten");
            tens.Add(11, "Eleven");
            tens.Add(12, "Twelve");
            tens.Add(13, "Thrteen");
            tens.Add(14, "Fourteen");
            tens.Add(15, "Fifteen");
            tens.Add(16, "Sixteen");
            tens.Add(17, "Seventeen");
            tens.Add(18, "Eighteen");
            tens.Add(19, "Ninteen");
            if (tens.ContainsKey(value))
            {
                englishEquvalent = tens[value];
            }

            return englishEquvalent;

        }
        private static string GetOnes(string onesPlaceValue)
        {
            int value = Convert.ToInt32(onesPlaceValue);
            string englishEquvalent = string.Empty;
            Dictionary<int, string> ones = new Dictionary<int, string>();
            ones.Add(1, " One");
            ones.Add(2, " Two");
            ones.Add(3, " Three");
            ones.Add(4, " Four");
            ones.Add(5, " Five");
            ones.Add(6, " Six");
            ones.Add(7, " Seven");
            ones.Add(8, " Eight");
            ones.Add(9, " Nine");

            if (ones.ContainsKey(value))
            {
                englishEquvalent = ones[value];
            }

            return englishEquvalent;
        }
        private static string GetSections(int section)
        {
            string sectionName = string.Empty;
            switch (section)
            {
                case 0:
                    sectionName = "Cents";
                    break;
                case 1:
                    sectionName = "Dollars";
                    break;
                case 2:
                    sectionName = "Thousand";
                    break;
                case 3:
                    sectionName = "Million";
                    break;
                case 4:
                    sectionName = "Billion";
                    break;
                case 5:
                    sectionName = "Trillion";
                    break;
                case 6:
                    sectionName = "Zillion";
                    break;
            }
            return sectionName;
        }
        private static bool ValidateInput(string input)
        {
            return Regex.IsMatch(input, "[0-9]{1,18}(\\.[0-9]{1,2})?"))
        }
    }
}
Santhosh
  • 729
  • 7
  • 19