How can I convert an integer into its verbal representation?
Asked Answered
T

14

58

Is there a library or a class/function that I can use to convert an integer to its verbal representation?

Example input:

4,567,788`

Example output:

Four million, Five hundred sixty-seven thousand, seven hundred eighty-eight

Thielen answered 16/2, 2009 at 19:35 Comment(0)
C
28

If you use the code found in converting numbers in to words C#, and you need it for decimal numbers, here is how to do it:

public string DecimalToWords(decimal number)
{
    if (number == 0)
        return "zero";

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

    string words = "";

    int intPortion = (int)number;
    decimal fraction = (number - intPortion)*100;
    int decPortion = (int)fraction;

    words = NumericToWords(intPortion);
    if (decPortion > 0)
    {
        words += " and ";
        words += NumericToWords(decPortion);
    }
    return words;
}
Coz answered 19/10, 2011 at 23:40 Comment(1)
When I'm using decimal in the amount, I do not want "And" to occur twice, one with "Number to Words" one with "Decimal", it should only occur when there is no decimal, if there is a decimal, it should occur with decimal only.Desperation
S
68

Currently the best, most robust, library for this is definitely Humanizer. It's open sourced and available as a NuGet package:

Console.WriteLine(4567788.ToWords()); // => four million five hundred and sixty-seven thousand seven hundred and eighty-eight

It also has a wide range of tools solving the small problems every application has with strings, enums, DateTimes, TimeSpans and so forth, and supports many different languages.

Console.WriteLine(4567788.ToOrdinalWords().Underscore().Hyphenate().ApplyCase(LetterCasing.AllCaps)); // => FOUR-MILLION-FIVE-HUNDRED-AND-SIXTY-SEVEN-THOUSAND-SEVEN-HUNDRED-AND-EIGHTY-EIGHTH
Simoniac answered 3/6, 2014 at 14:3 Comment(1)
Wow, that's multilingual: Afrikaans, Arabic, Bangla, BrazilianPortuguese, Dutch, English, Farsi, Finnish, French, German, Hebrew, Italian, NorwegianBokmal, Polish, Romanian, Russian, SerbianCyrl, Serbian, Slovenian, Spanish, Ukrainian. See at github.com/Humanizr/Humanizer/tree/dev/src/Humanizer/…Manumission
C
28

If you use the code found in converting numbers in to words C#, and you need it for decimal numbers, here is how to do it:

public string DecimalToWords(decimal number)
{
    if (number == 0)
        return "zero";

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

    string words = "";

    int intPortion = (int)number;
    decimal fraction = (number - intPortion)*100;
    int decPortion = (int)fraction;

    words = NumericToWords(intPortion);
    if (decPortion > 0)
    {
        words += " and ";
        words += NumericToWords(decPortion);
    }
    return words;
}
Coz answered 19/10, 2011 at 23:40 Comment(1)
When I'm using decimal in the amount, I do not want "And" to occur twice, one with "Number to Words" one with "Decimal", it should only occur when there is no decimal, if there is a decimal, it should occur with decimal only.Desperation
W
12

A fully recursive version:

private static string[] ones = {
    "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
    "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen",
};

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

private static string[] thous = { "hundred", "thousand", "million", "billion", "trillion", "quadrillion" };

private static string fmt_negative = "negative {0}";
private static string fmt_dollars_and_cents = "{0} dollars and {1} cents";
private static string fmt_tens_ones = "{0}-{1}"; // e.g. for twenty-one, thirty-two etc. You might want to use an en-dash or em-dash instead of a hyphen.
private static string fmt_large_small = "{0} {1}"; // stitches together the large and small part of a number, like "{three thousand} {five hundred forty two}"
private static string fmt_amount_scale = "{0} {1}"; // adds the scale to the number, e.g. "{three} {million}";

public static string ToWords(decimal number) {
    if (number < 0)
        return string.format(fmt_negative, ToWords(Math.Abs(number)));

    int intPortion = (int)number;
    int decPortion = (int)((number - intPortion) * (decimal) 100);

    return string.Format(fmt_dollars_and_cents, ToWords(intPortion), ToWords(decPortion));
}

private static string ToWords(int number, string appendScale = "") {
    string numString = "";
    // if the number is less than one hundred, then we're mostly just pulling out constants from the ones and tens dictionaries
    if (number < 100) {
        if (number < 20)
            numString = ones[number];
        else {
            numString = tens[number / 10];
            if ((number % 10) > 0)
                numString = string.Format(fmt_tens_ones, numString, ones[number % 10]);
        }
    } else {
        int pow = 0; // we'll divide the number by pow to figure out the next chunk
        string powStr = ""; // powStr will be the scale that we append to the string e.g. "hundred", "thousand", etc.

        if (number < 1000) { // number is between 100 and 1000
            pow = 100; // so we'll be dividing by one hundred
            powStr = thous[0]; // and appending the string "hundred"
        } else { // find the scale of the number
            // log will be 1, 2, 3 for 1_000, 1_000_000, 1_000_000_000, etc.
            int log = (int)Math.Log(number, 1000);
            // pow will be 1_000, 1_000_000, 1_000_000_000 etc.
            pow = (int)Math.Pow(1000, log);
            // powStr will be thousand, million, billion etc.
            powStr = thous[log];
        }

        // we take the quotient and the remainder after dividing by pow, and call ToWords on each to handle cases like "{five thousand} {thirty two}" (curly brackets added for emphasis)
        numString = string.Format(fmt_large_small, ToWords(number / pow, powStr), ToWords(number % pow)).Trim();
    }

    // and after all of this, if we were passed in a scale from above, we append it to the current number "{five} {thousand}"
    return string.Format(fmt_amount_scale, numString, appendScale).Trim();
}

It currently works up to the (short scale) quadrillions. Additional support (for larger numbers, or for the long scale) can be added simply by changing the thous variable.

Weary answered 26/11, 2013 at 17:46 Comment(0)
B
3

This solution takes advantage of C# 7.0's support for local functions. I also used the new digit separator to make the larger numbers more readable.

public static class NumberExtensions
{
    private const string negativeWord = "negative";
    private static readonly Dictionary<ulong, string> _wordMap = new Dictionary<ulong, string>
    {
        [1_000_000_000_000_000_000] = "quintillion",
        [1_000_000_000_000_000] = "quadrillion",
        [1_000_000_000_000] = "trillion",
        [1_000_000_000] = "billion",
        [1_000_000] = "million",
        [1_000] = "thousand",
        [100] = "hundred",
        [90] = "ninety",
        [80] = "eighty",
        [70] = "seventy",
        [60] = "sixty",
        [50] = "fifty",
        [40] = "forty",
        [30] = "thirty",
        [20] = "twenty",
        [19] = "nineteen",
        [18] = "eighteen",
        [17] = "seventeen",
        [16] = "sixteen",
        [15] = "fifteen",
        [14] = "fourteen",
        [13] = "thirteen",
        [12] = "twelve",
        [11] = "eleven",
        [10] = "ten",
        [9] = "nine",
        [8] = "eight",
        [7] = "seven",
        [6] = "six",
        [5] = "five",
        [4] = "four",
        [3] = "three",
        [2] = "two",
        [1] = "one",
        [0] = "zero"
    };

    public static string ToWords(this short num)
    {
        var words = ToWords((ulong)Math.Abs(num));
        return num < 0 ? $"{negativeWord} {words}" : words;
    }

    public static string ToWords(this ushort num)
    {
        return ToWords((ulong)num);
    }

    public static string ToWords(this int num)
    {
        var words = ToWords((ulong)Math.Abs(num));
        return num < 0 ? $"{negativeWord} {words}" : words;
    }

    public static string ToWords(this uint num)
    {
        return ToWords((ulong)num);
    }

    public static string ToWords(this long num)
    {
        var words = ToWords((ulong)Math.Abs(num));
        return num < 0 ? $"{negativeWord} {words}" : words;
    }

    public static string ToWords(this ulong num)
    {
        var sb = new StringBuilder();
        var delimiter = String.Empty;

        void AppendWords(ulong dividend)
        {
            void AppendDelimitedWord(ulong key)
            {
                sb.Append(delimiter);
                sb.Append(_wordMap[key]);
                delimiter = 20 <= key && key < 100 ? "-" : " ";
            }
            
            if (_wordMap.ContainsKey(dividend))
            {
                AppendDelimitedWord(dividend);
            }
            else
            {
                var divisor = _wordMap.First(m => m.Key <= dividend).Key;
                var quotient = dividend / divisor;
                var remainder = dividend % divisor;

                if (quotient > 0 && divisor >= 100)
                {
                    AppendWords(quotient);
                }

                AppendDelimitedWord(divisor);

                if (remainder > 0)
                {   
                    AppendWords(remainder);
                }
            }
        }

        AppendWords(num);
        return sb.ToString();
    }    
}

The meat is in the last ToWords overload.

Barrus answered 8/7, 2017 at 1:21 Comment(1)
In what way does it take advantage of C# 7.0's support for local functions?Salic
N
2

JavaScript version:

Number.prototype.numberToWords = function () {
    var unitsMap = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"];
    var tensMap = ["zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"];

    var num = this.valueOf();
    if (Math.round(num == 0)) {
        return "zero";
    }
    if (num < 0) {
        var positivenum = Math.abs(num);
        return "minus " + Number(positivenum).numberToWords();
    }
    var words = "";
    if (Math.floor(num / 1000000) > 0) {
        words += Math.floor(num / 1000000).numberToWords() + " million ";
        num = Math.floor(num % 1000000);
    }
    if (Math.floor(num / 1000) > 0) {
        words += Math.floor(num / 1000).numberToWords() + " thousand ";
        num = Math.floor(num % 1000);
    }
    if (Math.floor(num / 100) > 0) {
        words += Math.floor(num / 100).numberToWords() + " hundred ";
        num = Math.floor(num % 100);
    }
    if (Math.floor(num > 0)) {
        if (words != "") {
            words += "and ";
        }
        if (num < 20) {
        words += unitsMap[num];
        }
        else {
            words += tensMap[Math.floor(num / 10)];
            if ((num % 10) > 0) {
                words += "-" + unitsMap[Math.round(num % 10)];
            }
        }
    }
    return words.trim();
}
Neutrality answered 8/8, 2014 at 5:38 Comment(0)
P
2

Spanish version:

public static string numeroALetras(int number)
{
    if (number == 0)
        return "cero";

    if (number < 0)
        return "menos " + numeroALetras(Math.Abs(number));

    string words = "";

    if ((number / 1000000) > 0)
    {
        words += numeroALetras(number / 1000000) + " millón ";
        number %= 1000000;
    }

    if ((number / 1000) > 0)
    {
        words += (number / 1000) == 1? "mil ": numeroALetras(number / 1000) + " mil ";
        number %= 1000;
    }
    if ((number / 100) == 1)
    {
        if (number == 100)
            words += "cien";
        else words += (number / 100)> 1? numeroALetras(number / 100) + " ciento ":"ciento ";
        number %= 100;
    }
    if ((number / 100) > 1)
    {
        var hundredMap = new[] {"","", "dosc", "tresc", "cuatroc", "quin", "seisc", "sietec", "ochoc", "novec" };
        if (number > 199)
            words += hundredMap[number/100] + "ientos ";
        else {
            words += numeroALetras(number / 100) + " ientos ";
        }
        number %= 100;
    }

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

        var unitsMap = new[] { "cero", "uno", "dos", "tres", "cuatro", "cinco", "seis", "siete", "ocho", "nueve", "diez", "once", "doce", "trece", "catorce", "quince", "dieciseis", "diecisiete", "dieciocho", "diecinueve", "veinte" };
        var tensMap = new[] { "cero", "diez", "veinti", "treinta", "cuarenta", "cincuenta", "sesenta", "setenta", "ochenta", "noventa" };
        
        if (number < 21)
            words += unitsMap[number];
        else
        {                    
            words += tensMap[number / 10];
            if ((number % 10) > 0)
                words += ((number % 10)>2?" y ": "") + unitsMap[number % 10];                    
        }
    }

    return words;
}
Peruzzi answered 1/6, 2017 at 15:12 Comment(0)
M
2

I created a web API that converts numbers to words using C#.

Input is a whole number or a number with decimal points in 48-hour time.

The call comes from a front-end application using an Ajax Post method and returns the converted result in the web page.

I shared in GitHub: https://github.com/marvinglennlacuna/NumbersToWordsConverter.Api

With the following technical implementation:

  1. MVC structured
  2. API controller
  3. Service
  4. Model
  5. Error handling
  6. Unit testing using MSTest
  7. Code coverage - 98%
  8. jQuery

And with technical documentation about the following:

  1. Purpose
  2. Prerequisites
  3. Functional Requirements
  4. Process diagram and output

Result via web page (US-001)

US-001 Convert numbers to words via web page process

Enter image description here

US-001 Convert numbers to words via web page output

Enter image description here

Result via Postman (US-002)

US-002 - Convert numbers to words via Postman process

Enter image description here

US-002 - Convert numbers to words via Postman output

Enter image description here

Manilla answered 20/10, 2017 at 2:51 Comment(0)
E
1

I have written a C# function, NumIntToWords(String NumIn), that provides a simple, short, and efficient method of converting integer numbers to words in C#, complying with US English grammar rules.

The function uses my devised method of SLST (Single Loop String Triplet).

Unlike other methods I had seen used here and elsewhere, the function has the following features:

  • Simple, short, and fast.
  • It does not use switch/case statements.
  • It does not require the use of extra spaces in strings or trimming strings.
  • It does not use recursion.
  • It does not use math functions (only one math for creating the string triplet).
  • You can simply increase scale beyond Trillion by a simple increase of the scale array without any additional coding necessary.
  • It compiles into a very shortcode.
  • No extra libraries.

I have opted for the integer number to be converted to be passed as a string so you can handle very large integer numbers easily.

You can use it like this:

Console.WriteLine(NumIntToWords("1991345678974"));

Output:

One Trillion Nine Hundred Ninety-One Billion Three Hundred Forty-Five Million Six Hundred Seventy-Eight Thousand Nine Hundred Seventy-Four

C# SLST Function Method (c) Mohsen Alyafei:

/*********************************************************************
* @function    : NumIntToWords(String NumIn)
* @purpose     : Converts Unsigned Integers to Words
*                Using the SLST Method (C) Mohsen Alyafei 2019.
*                Does not check for Non-Numerics or +/- signs
* @version     : 2.11
* @author      : Mohsen Alyafei
* @Licence     : MIT
* @date        : 03 April 2022
* @in_param    : {NumIn} (Required): Number in string format
* @returns     : {string}: The number in English Words US Grammar
**********************************************************************/
public static string NumIntToWords(String NumIn) {
    if (NumIn.TrimStart('0') == "")
        return "Zero";                   // If empty or zero return Zero

    string[] T10s = {"", "One", "Two", "Three", "Four", "Five", "Six",
                     "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve",
                     "Thirteen", "Fourteen", "Fifteen", "Sixteen",
                     "Seventeen", "Eighteen", "Nineteen"},
             T20s = {"", "", "Twenty", "Thirty", "Forty", "Fifty",
                     "Sixty", "Seventy","Eighty","Ninety"},
           Scales = {"", "Thousand", "Million", "Billion", "Trillion"}; // Increase scale here (unlimited)

    NumIn = new String('0', NumIn.Length * 2 % 3) + NumIn; // Make it a String Triplet
    String numToWords = "", wordTriplet, Triplet;

    for (int digits = NumIn.Length; digits > 0; digits -= 3) { // Single Loop
        Triplet = NumIn.Substring(NumIn.Length - digits, 3);   // Get next Triplet
        if (Triplet != "000") {                                // Convert Only if not empty
            wordTriplet = "";
            int ScalePos = digits / 3 - 1,                     // Scale name position
                    hund = int.Parse("" + Triplet[0]),
                    tens = int.Parse(Triplet.Substring(1, 2)),
                    ones = int.Parse("" + Triplet[2]);
             wordTriplet = (hund>0 ? T10s[hund] + " Hundred" : "") +
                           (tens>0 && hund>0 ? " " : "") +
                           (tens<20 ? T10s[tens]: T20s[int.Parse("" + Triplet[1])] + (ones>0? "-" + T10s[ones] : "")) +
                           (ScalePos>0 ? " " : "") + Scales[ScalePos];  // Add Scale Name to Triplet Word
             numToWords += (numToWords != "" ? " " : "") + wordTriplet; // Concatenate Next Triplet Word
        }
    }                   // Loop for the next Triplet
    return numToWords;  // Return full Number in Words
}
Epidaurus answered 4/4, 2022 at 18:31 Comment(0)
E
0

Use:

Imports System.Text

Public Class NumberWriter

    Public Shared Function Parse(ByVal Number As String) As String
        If Not AreNumbers(Number) Then Return ""
        Dim TempQueue As New Queue(Of String)
        For Each ItemA As Char In Number.Replace(",", "").Reverse
            TempQueue.Enqueue(ItemA)
        Next
        Dim Blocks As New List(Of String)
        Dim BlockEmpty As New List(Of Boolean)
        Do
            Dim TempBlock As New StringBuilder(3)
            TempBlock.Append(TempQueue.Dequeue)
            If TempQueue.Count > 0 Then
                TempBlock.Append(TempQueue.Dequeue)
                If TempQueue.Count > 0 Then
                    TempBlock.Append(TempQueue.Dequeue)
                End If
            End If
            Blocks.Add(StrReverse(TempBlock.ToString))
            BlockEmpty.Add(TempBlock.ToString = "000")
            If TempQueue.Count < 1 Then Exit Do
        Loop
        Dim ResultStack As New Stack(Of String)
        For int1 As Integer = 0 To Blocks.Count - 1
            ResultStack.Push(ReadBlock(Blocks(int1)) & If(Not int1 = 0, If(Not BlockEmpty(int1), " " & CapitalizeWord(GetPlaceValueSet(int1)) & If(BlockEmpty(int1 - 1), "", ", "), ""), ""))
        Next
        Dim Result1 As String = ""
        Do Until ResultStack.Count < 1
            Result1 &= ResultStack.Pop
        Loop
        Return RemoveGrammarErrors(Result1)
    End Function

    Private Shared Function RemoveGrammarErrors(ByVal Str As String) As String
        Dim tstr As String = Str
        tstr.Replace("  ", " ")
        tstr.Replace(" , ", ", ")
        Return tstr
    End Function

    Private Shared Function AreNumbers(ByVal Str1 As String) As Boolean
        Dim Numbers() As String = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ","}
        For Each ItemA As Char In Str1
            Dim IsN As Boolean = False
            For Each ItemB As String In Numbers
                If ItemA = ItemB Then IsN = True
            Next
            If Not IsN Then
                Return False
            End If
        Next
        Return True
    End Function

    Private Shared Function ReadBlock(ByVal Block As String)
        Select Case Block.Length
            Case 1
                Return ReadSingleDigit(Block)
            Case 2
                Return ReadTwoDigits(Block)
            Case 3
                Return ReadThreeDigits(Block)
            Case Else
                Throw New Exception
        End Select
    End Function

    Private Shared Function ReadThreeDigits(ByVal Digits As String)
        If Digits.Length > 3 Then Throw New ArgumentException("There are too many digits.")
        Dim Result As String = ""
        If Not Digits(0) = "0" Then
            Result &= ReadSingleDigit(Digits(0)) & " Hundred "
        End If
        Result &= ReadTwoDigits(Digits.Substring(1))
        Return Result
    End Function

    Private Shared Function ReadTwoDigits(ByVal Digits As String)
        If Digits.Length > 2 Then Throw New ArgumentException("There are too many digits.")
        Select Case Digits(0)
            Case "0"
                Return ReadSingleDigit(Digits(1))
            Case "1"
                Return ReadTeenNumber(Digits)
            Case Else
                Return ReadFirstInNumberPair(Digits(0)) & If(Digits(1) = "0", "", "-" & ReadSingleDigit(Digits(1)))
        End Select
    End Function

    Private Shared Function ReadSingleDigit(ByVal Digit As String) As String
        If Not Digit.Length = 1 Then Throw New ArgumentException("There must be only one digit and it must be more than zero.")
        Select Case Digit
            Case "0"
                Return ""
            Case "1"
                Return "One"
            Case "2"
                Return "Two"
            Case "3"
                Return "Three"
            Case "4"
                Return "Four"
            Case "5"
                Return "Five"
            Case "6"
                Return "Six"
            Case "7"
                Return "Seven"
            Case "8"
                Return "Eight"
            Case "9"
                Return "Nine"
            Case Else
                Throw New Exception()
        End Select
    End Function

    Private Shared Function ReadTeenNumber(ByVal Num As String) As String
        Select Case Num
            Case "11"
                Return "Eleven"
            Case "12"
                Return "Twelve"
            Case "13"
                Return "Thirteen"
            Case "14"
                Return "Fourteen"
            Case "15"
                Return "Fifteen"
            Case "16"
                Return "Sixteen"
            Case "17"
                Return "Seventeen"
            Case "18"
                Return "Eighteen"
            Case "19"
                Return "Nineteen"
            Case Else
                Throw New Exception()
        End Select
    End Function

    Private Shared Function ReadFirstInNumberPair(ByVal Num As String) As String
        If Not (Num > 1 OrElse Num < 10) Then Throw New ArgumentException("Number must be more than 1 and less than 10")
        Select Case Num
            Case "2"
                Return "Twenty"
            Case "3"
                Return "Thirty"
            Case "4"
                Return "Fourty"
            Case "5"
                Return "Fifty"
            Case "6"
                Return "Sixty"
            Case "7"
                Return "Seventy"
            Case "8"
                Return "Eighty"
            Case "9"
                Return "Ninety"
            Case Else
                Throw New Exception()
        End Select
    End Function

    Private Shared Function CapitalizeWord(ByVal Word As String) As String
        Return Word.Substring(0, 1).ToUpper & Word.Substring(1)
    End Function

    Private Shared Function GetPlaceValueSet(ByVal Num As Byte) As String
        Select Case Num
            Case 0
                Return "" 'Hundreds
            Case 1
                Return "Thousand"
            Case 2
                Return "Million"
            Case 3
                Return "Billion"
            Case 4
                Return "Trillion"
            Case 5
                Return "Quadrillion"
            Case 6
                Return "Quintillion"
            Case 7
                Return "Sextillion"
            Case 8
                Return "Septillion"
            Case 9
                Return "Octillion"
            Case 10
                Return "Nonillion"
            Case 11
                Return "octillion"
            Case 12
                Return "nonillion"
            Case 13
                Return "decillion"
            Case 14
                Return "undecillion"
            Case 15
                Return "dodecillion,"
            Case 16
                Return "tredecillion"
            Case 17
                Return "quattuordecillion"
            Case 18
                Return "quindecillion"
            Case 19
                Return "sexdecillion"
            Case 20
                Return "septendecillion"
            Case 21
                Return "octodecillion"
            Case 22
                Return "novemdecillion"
            Case 23
                Return "vigintillion"
            Case 24
                Return "unvigintillion"
            Case 25
                Return "dovigintillion"
            Case 26
                Return "trevigintillion"
            Case 27
                Return "quattuorvigintillion"
            Case 28
                Return "quinvigintillion"
            Case 29
                Return "sexvigintillion"
            Case 30
                Return "septenvigintillion"
            Case 31
                Return "octovigintillion"
            Case 32
                Return "novemvigintillion"
            Case 33
                Return "trigintillion"
            Case 34
                Return "untrigintillion"
            Case 35
                Return "dotrigintillion"
            Case 36
                Return "tretrigintillion"
            Case 37
                Return "quattuortrigintillion"
            Case 38
                Return "quintrigintillion"
            Case 39
                Return "sextrigintillion"
            Case 40
                Return "septentrigintillion"
            Case 41
                Return "octotrigintillion"
            Case Else
                Throw New Exception
        End Select
    End Function
End Class

It's in VB.NET and coverts number to verbal. It handles numbers up to 123 characters long.

Eleven answered 24/9, 2012 at 6:16 Comment(0)
J
0

Functionality with a more detailed approach:

public static class NumberToWord
{
    private static readonly Dictionary<long, string> MyDictionary = new Dictionary<long, string>();

    static NumberToWord()
    {
        MyDictionary.Add(1000000000000000, "quadrillion");
        MyDictionary.Add(1000000000000, "trillion");
        MyDictionary.Add(1000000000, "billion");
        MyDictionary.Add(1000000, "million");
        MyDictionary.Add(1000, "thousand");
        MyDictionary.Add(100, "hundread");
        MyDictionary.Add(90, "ninety");
        MyDictionary.Add(80, "eighty");
        MyDictionary.Add(70, "seventy");
        MyDictionary.Add(60, "sixty");
        MyDictionary.Add(50, "fifty");
        MyDictionary.Add(40, "fourty");
        MyDictionary.Add(30, "thirty");
        MyDictionary.Add(20, "twenty");
        MyDictionary.Add(19, "nineteen");
        MyDictionary.Add(18, "eighteen");
        MyDictionary.Add(17, "seventeen");
        MyDictionary.Add(16, "sixteen");
        MyDictionary.Add(15, "fifteen");
        MyDictionary.Add(14, "fourteen");
        MyDictionary.Add(13, "thirteen");
        MyDictionary.Add(12, "twelve");
        MyDictionary.Add(11, "eleven");
        MyDictionary.Add(10, "ten");
        MyDictionary.Add(9, "nine");
        MyDictionary.Add(8, "eight");
        MyDictionary.Add(7, "seven");
        MyDictionary.Add(6, "six");
        MyDictionary.Add(5, "five");
        MyDictionary.Add(4, "four");
        MyDictionary.Add(3, "three");
        MyDictionary.Add(2, "two");
        MyDictionary.Add(1, "one");
        MyDictionary.Add(0, "zero");
    }

    /// <summary>
    /// To the verbal.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static string ToVerbal(this int value)
    {
        return ToVerbal((long) value);
    }

    /// <summary>
    /// To the verbal.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static string ToVerbal(this long value)
    {
        if (value == 0)
            return MyDictionary[value];

        if (value < 0)
            return $" negative {ToVerbal(Math.Abs(value))}";

        var builder = new StringBuilder();

        for (var i = 1000000000000000; i >= 1000; i = i/1000)
            value = ConstructWord(value, builder, i);

        value = ConstructWord(value, builder, 100);

        for (var i = 90; i >= 20; i = i - 10)
            value = ConstructWordForTwoDigit(value, builder, i);

        if (MyDictionary.ContainsKey(value))
            builder.AppendFormat("{0}" + MyDictionary[value], builder.Length > 0
                ? " "
                : string.Empty);

        return builder.ToString();
    }

    private static long ConstructWord(long value, StringBuilder builder, long key)
    {
        if (value >= key)
        {
            var unit = (int) (value/key);
            value -= unit*key;
            builder.AppendFormat(" {0} {1} " + MyDictionary[key], builder.Length > 0
                ? ", "
                : string.Empty, ToVerbal(unit));
        }
        return value;
    }

    private static long ConstructWordForTwoDigit(long value, StringBuilder builder, long key)
    {
        if (value >= key)
        {
            value -= key;
            builder.AppendFormat(" {0} " + MyDictionary[key], builder.Length > 0
                ? " "
                : string.Empty);
        }
        return value;
    }
}

I have user string interpolation which is only available in 4.6.1.

Jenniejennifer answered 23/11, 2016 at 14:38 Comment(0)
A
-1

Use:

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = Console.ReadLine();
            ConvertMyword(int.Parse(s));

            Console.Read();
        }

        static void ConvertMyword(int number)
        {
            int flag = 0;
            int lflag = 0;
            string words = String.Empty;
            string[] places = { "ones", "ten", "hundred", "thousand", "ten thousand", "lacs", "tenlacs", "crore", "tencrore" };
            string rawnumber = number.ToString();
            char[] a = rawnumber.ToCharArray();
            Array.Reverse(a);
            for (int i = a.Length - 1; i >= 0; i--)
            {
                if (i % 2 == 0 && i > 2)
                {
                    if (int.Parse(a[i].ToString()) > 1)
                    {
                        if (int.Parse(a[i - 1].ToString()) == 0)
                        {
                            words = words + getNumberStringty(int.Parse(a[i].ToString())) + " " + places[i - 1] + " ";
                        }
                        else
                        {
                            words = words + getNumberStringty(int.Parse(a[i].ToString())) + " ";
                        }
                    }
                    else if (int.Parse(a[i].ToString()) == 1)
                    {
                        if (int.Parse(a[i - 1].ToString())== 0)
                        {
                            words = words + "Ten" + " ";
                        }
                        else
                        {
                            words = words + getNumberStringteen(int.Parse(a[i - 1].ToString())) + " ";
                        }
                        flag = 1;
                    }
                }
                else
                {
                    if (i == 1 || i == 0)
                    {
                        if (int.Parse(a[i].ToString()) > 1)
                        {
                            words = words + getNumberStringty(int.Parse(a[i].ToString())) + " " + getNumberString(int.Parse(a[0].ToString())) + " ";
                            break;
                        }
                        else if (int.Parse(a[i].ToString()) == 1)
                        {
                            if (int.Parse(a[i - 1].ToString()) == 0)
                            {
                                words = words + "Ten" + " ";
                            }
                            else
                            {
                                words = words + getNumberStringteen(int.Parse(a[i - 1].ToString())) + " ";
                            }

                            break;
                        }
                        else if (int.Parse(a[i - 1].ToString()) != 0)
                        {
                            words = words + getNumberString(int.Parse(a[i - 1].ToString())) + " ";
                            break;
                        }
                        else
                        {
                            break;
                        }
                    }
                    else
                    {
                        if (flag == 0)
                        {
                            for(int l=i; l>=0; l--)
                            {
                                if (int.Parse(a[l].ToString()) != 0)
                                {
                                    lflag = 1;
                                }
                            }
                            if (lflag == 1 && int.Parse(a[i].ToString()) != 0)
                            {

                                words = words + getNumberString(int.Parse(a[i].ToString())) + " " + places[i] + " ";
                                lflag = 0;
                            }
                            else if(lflag == 0)
                            {
                                //words = words + getNumberString(int.Parse(a[i].ToString())) + " " + places[i] + " ";
                                lflag = 0;
                                break;
                            }
                        }
                        else
                        {
                            words = words + " " + places[i] + " ";
                            flag = 0;
                        }
                    }
                }
            }
            Console.WriteLine(words);
        }

        static string getNumberString(int num)
        {
            string Word = String.Empty;
            switch (num)
            {
                case 1:
                    Word = "one";
                    break;

                case 2:
                    Word = "two";
                    break;

                case 3:
                    Word = "three";
                    break;

                case 4:
                    Word = "four";
                    break;

                case 5:
                    Word = "five";
                    break;

                case 6:
                    Word = "six";
                    break;
                case 7:
                    Word = "seven";
                    break;

                case 8:
                    Word = "eight";
                    break;

                case 9:
                    Word = "nine";
                    break;
            }
            return Word;
        }

        static string getNumberStringty(int num)
        {
            string Word = String.Empty;
            switch (num)
            {
                case 2:
                    Word = "twenty";
                    break;

                case 3:
                    Word = "thirty";
                    break;

                case 4:
                    Word = "fourty";
                    break;

                case 5:
                    Word = "fifty";
                    break;

                case 6:
                    Word = "sixty";
                    break;
                case 7:
                    Word = "seventy";
                    break;

                case 8:
                    Word = "eighty";
                    break;

                case 9:
                    Word = "ninty";
                    break;
            }
            return Word;
        }

        static string getNumberStringteen(int num)
        {
            string Word = String.Empty;
            switch (num)
            {
                case 1:
                    Word = "eleven";
                    break;

                case 2:
                    Word = "tewlve";
                    break;

                case 3:
                    Word = "thirteen";
                    break;

                case 4:
                    Word = "fourteen";
                    break;

                case 5:
                    Word = "fifteen";
                    break;

                case 6:
                    Word = "sixteen";
                    break;

                case 7:
                    Word = "seventeen";
                    break;

                case 8:
                    Word = "eighteen";
                    break;

                case 9:
                    Word = "ninteen";
                    break;
            }
            return Word;
        }
    }
}
Acarpous answered 17/1, 2013 at 12:13 Comment(1)
That is a lot of redundant code. Isn't that what maps are for?Salic
J
-1

This class converts a float or double (till 2 precision).

class ConversionClass
{
    private static Dictionary<int, string> InitialNumbers = new Dictionary<int, string>();
    private static Dictionary<int, string> MultipleOfTen = new Dictionary<int, string>();
    private static Dictionary<int, string> MultipleOfHundered = new Dictionary<int, string>();

    private static void InitializeStatic()
    {
        //InitialNumbers.Add(0, "zero");
        InitialNumbers.Add(1, "one");
        InitialNumbers.Add(2, "two");
        InitialNumbers.Add(3, "three");
        InitialNumbers.Add(4, "four");
        InitialNumbers.Add(5, "five");
        InitialNumbers.Add(6, "six");
        InitialNumbers.Add(7, "seven");
        InitialNumbers.Add(8, "eight");
        InitialNumbers.Add(9, "nine");
        InitialNumbers.Add(10, "ten");
        InitialNumbers.Add(11, "eleven");
        InitialNumbers.Add(12, "tweleve");
        InitialNumbers.Add(13, "thirteen");
        InitialNumbers.Add(14, "fourteen");
        InitialNumbers.Add(15, "fifteen");
        InitialNumbers.Add(16, "sixteen");
        InitialNumbers.Add(17, "seventeen");
        InitialNumbers.Add(18, "eighteen");
        InitialNumbers.Add(19, "nineteen");

        MultipleOfTen.Add(1, "ten");
        MultipleOfTen.Add(2, "twenty");
        MultipleOfTen.Add(3, "thirty");
        MultipleOfTen.Add(4, "fourty");
        MultipleOfTen.Add(5, "fifty");
        MultipleOfTen.Add(6, "sixty");
        MultipleOfTen.Add(7, "seventy");
        MultipleOfTen.Add(8, "eighty");
        MultipleOfTen.Add(9, "ninety");

        MultipleOfHundered.Add(2, "hundred");  //                100
        MultipleOfHundered.Add(3, "thousand"); //              1 000
        MultipleOfHundered.Add(4, "thousand"); //             10 000
        MultipleOfHundered.Add(5, "thousand"); //            100 000
        MultipleOfHundered.Add(6, "million");  //          1 000 000
        MultipleOfHundered.Add(7, "million");  //        100 000 000
        MultipleOfHundered.Add(8, "million");  //      1 000 000 000
        MultipleOfHundered.Add(9, "billion");  //  1 000 000 000 000
    }

    public static void Main()
    {
        InitializeStatic();
        Console.WriteLine("Enter number: ");
        var userInput = Console.ReadLine();
        double userValue;
        if (double.TryParse(userInput, out userValue))  // userValue = 193524019.50
        {
            int decimalPortion = (int)userValue;
            //var fractionPortion = Math.Ceiling(((userValue < 1.0) ? userValue : (userValue % Math.Floor(userValue))) * 100);
            int fractionPortion = (int)(userValue * 100) - ((int)userValue * 100);

            int digit; int power;
            StringBuilder numberInText = new StringBuilder();

            while (decimalPortion > 0)
            {
                GetDigitAndPower(decimalPortion, out digit, out power);
                numberInText.Append(ConvertToText(ref decimalPortion, ref digit, ref power));
                if (decimalPortion > 0)
                {
                    decimalPortion = GetReminder(decimalPortion, digit, power);
                }
            }
            numberInText.Append(" point ");
            while (fractionPortion > 0)
            {
                GetDigitAndPower(fractionPortion, out digit, out power);
                numberInText.Append(ConvertToText(ref fractionPortion, ref digit, ref power));
                if (fractionPortion > 0)
                {
                    fractionPortion = GetReminder(fractionPortion, digit, power);
                }
            }
            Console.WriteLine(numberInText.ToString());
        }
        Console.ReadKey();
    }

    private static int GetReminder(int orgValue, int digit, int power)
    {
        int returningValue = orgValue - (digit * (int)Math.Pow(10, power));
        return returningValue;
    }

    private static void GetDigitAndPower(int originalValue, out int digit, out int power)
    {
        for (power = 0, digit = 0; power < 10; power++)
        {
            var divisionFactor = (int)Math.Pow(10, power);
            int operationalValue = (originalValue / divisionFactor);
            if (operationalValue <= 0)
            {
                power = power - 1;
                digit = (int)(originalValue / Math.Pow(10, power));
                break;
            }
        }
    }

    private static string ConvertToText(ref int orgValue, ref int digit, ref int power)
    {
        string numberToText = string.Empty;

        if (power < 2)
        {
            if (InitialNumbers.ContainsKey(orgValue))
            {
                // This is for number 1 to 19
                numberToText = InitialNumbers[orgValue];
                orgValue = 0;
            }
            else if (MultipleOfTen.ContainsKey(digit))
            {
                // This is for multiple of 10 (20, 30, .. 90)
                numberToText = MultipleOfTen[digit];
            }
        }
        else
        {
            if (power < 4)
            {
                numberToText = string.Format("{0} {1}", InitialNumbers[digit], MultipleOfHundered[power]);
            }
            else
            {
                StringBuilder sb = new StringBuilder();
                int multiplicationFactor = power / 3;
                int innerOrgValue = (int) (orgValue / Math.Pow(10, (multiplicationFactor * 3)));
                digit = innerOrgValue;
                var multiple = MultipleOfHundered[power];
                power = power - ((int)Math.Ceiling(Math.Log10(innerOrgValue)) - 1);

                int innerPower = 0;
                int innerDigit = 0;
                while (innerOrgValue > 0)
                {
                    GetDigitAndPower(innerOrgValue, out innerDigit, out innerPower);
                    var text = ConvertToText(ref innerOrgValue, ref innerDigit, ref innerPower);
                    sb.Append(text);
                    sb.Append(" ");
                    if (innerOrgValue > 0)
                    {
                        innerOrgValue = GetReminder(innerOrgValue, innerDigit, innerPower);
                    }
                }
                sb.Append(multiple);
                numberToText = sb.ToString();
            }
        }
        return numberToText + " ";
    }
}
Joan answered 25/6, 2015 at 2:43 Comment(3)
@Weary 's solution is also good but it fails for value : 10 000, 100 000Joan
What is "2 precision"?Salic
@Joan it works if you don't put a space in the numberWeary
S
-1

The following C# console app code accepts a monetary value in numbers up to 2 decimals and prints it in English. You can use it as a reference.

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})?"))
        }
    }
}
Simpleminded answered 22/3, 2017 at 1:23 Comment(0)
R
-2

A solution that takes up less code.

The most important part is only a couple of lines:

static Func<long, string> remainder = t => t > 0 ? " " + ToEN(t) : "";

public static string ToEN(this long val, double d = 20, long th = 20)
{
    switch ((long)d)
    {
        case 20:   return val >= d ? ToEN(val, 1e2)             : en[val];
        case 100:  return val >= d ? ToEN(val, 1e3, 100)        : en[val / 10 * 10] + remainder(val % 10);
        default:   return val >= d ? ToEN(val, d * 1e3,(long)d) : ToEN(val / th) + " " + en[th] + remainder(val % th);
    }
}

Full code is available at https://dotnetfiddle.net/wjr4hF.

Rea answered 1/12, 2016 at 15:7 Comment(1)
Re "The most important part is only a couple of lines": Indeed. Especially in light of the redundancy monstrosities of previous answers. However, it ought to be explained. Some recursive thingamajiggy? What allows it to be so compact? What is the gist / secret sauce? (But *** *** *** *** *** *** *** *** *** without *** *** *** *** *** *** *** *** *** "Edit:", "Update:", or similar - the answer should appear as if it was written today)Salic

© 2022 - 2024 — McMap. All rights reserved.