Search code examples
c#stringbuilderdata-conversion

How would I convert a ulong data type input to a string for verbal number output?


I am currently trying to make an application in C# that takes a ulong number input and outputs the verbal representation of the number (i.e. 12 to "twelve", 45238 to "forty five thousand two hundred thirty eight", etc.) and I'd like for it to be able to pass uLong.MaxValue.

I am new to programming and really struggling with the concept. I've tried to implement Lists and StringBuilder earlier because I figured they could be useful, but I could not figure it out. I am trying to adapt the base code so that it works for ulong data types but I get the following errors:

error CS0121: The call is ambiguous between the following methods or properties: 'Math.Abs(decimal)' and 'Math.Abs(float)' error CS1503: Argument 1: cannot convert from 'string' to 'ulong'

Here is the base code:

using System;
using static System.Console;
using System.Text;
using System.Text.RegularExpressions;
using System.Numerics;

namespace NumberToText
{
    class Program
    {
        public static string ConvertToText(ulong number)
        {
            if (number == 0)
            return "zero";

        if (number < 0)
            return "minus " + ConvertToText(Math.Abs(number));

        string words = "";

        if ((number / 1000000) > 0)
        {
            words += ConvertToText(number / 1000000) + " million ";
            number %= 1000000;
        }

        if ((number / 1000) > 0)
        {
            words += ConvertToText(number / 1000) + " thousand ";
            number %= 1000;
        }

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

        if (number > 0)
        {
            if (words != "")
                words += "and ";

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

            if (number < 20)
                words += units[number];
            else
            {
                words += tens[number / 10];
                if ((number % 10) > 0)
                    words += "-" + units[number % 10];
            }
        }

        return words;
        }

        static void Main(string[] args)
        {
            Write("Enter a number: ");
            var number = ReadLine();

            ConvertToText(number);
            
        }
    }
}


Solution

  • error CS0121: The call is ambiguous between the following methods or properties: 'Math.Abs(decimal)' and 'Math.Abs(float)'

    The first error is telling you that there is no overload for Abs which takes a ulong argument, and it's ambiguous which candidates it should use (either decimal or float).

    To resolve this, you must cast the value yourself. Also note that you then have to cast the result of Abs back to ulong before passing the result to your method:

    if (number < 0)
        return "minus " + ConvertToText((ulong) Math.Abs((decimal) number));
    

    However it should be pointed out that a ulong is an unsigned long, which means it will never be negative and therefore this check is not needed.


    error CS1503: Argument 1: cannot convert from 'string' to 'ulong'

    The second error is telling you that there is no implicit conversion from string to ulong. In order to resolve this, we can use ulong.Parse or ulong.TryParse. Since the input is not guaranteed to be a valid ulong, we should use TryParse so we can add some error handling and let the user try again if they entered invalid input.

    TryParse takes a string parameter and an out parameter that will be set to the converted value, and it returns a bool that indicates if the conversion was successful. So we can implement it something like:

    Console.Write("Enter a number: ");
    var input = Console.ReadLine();
    
    ulong number;
    
    while (!ulong.TryParse(input, out number))
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.Write("Invalid input, please try again: ");
        Console.ResetColor();
        input = Console.ReadLine();
    }
    
    string result = ConvertToText(number);
    
    Console.WriteLine(result);