Подтвердить что ты не робот

.NET преобразует число в строковое представление (от 1 до одного, от 2 до два и т.д.)

Есть ли встроенный метод в .NET для преобразования числа в строковое представление числа? Например, 1 становится единым, 2 становится равным двум и т.д.

4b9b3361

Ответ 1

Я всегда был поклонником рекурсивного метода

  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);
}

Источник

Ответ 2

А, может быть, не класс, чтобы сделать это, но был вопрос для гольфа с кодом, который я предоставил для примера С# для:

Code Golf: число для слов

Однако, это не самый легкий для чтения, и он подходит только к decimal.MaxValue, поэтому я написал новую версию, которая будет настолько высокой, насколько вам нужно.

Я не мог найти никакой информации о значениях выше, чем vigintillions, но если вы добавите значения в массив you [], вы можете продолжить движение, насколько вам угодно. Он по-прежнему не поддерживает фракции, но я думаю о том, чтобы добавить это в какой-то момент.

    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();
    }

Я тестировал его с помощью Decimal.MaxValue, добавленного к себе, чтобы создать большое количество:

семь октодециллионов, девятьсот двадцать два полугодия, восемьсот шестнадцать полдециллионов, двести пятьдесят один квадцикл, четыреста двадцать шесть кватервондиков, четыреста тридцать три триллиона, семьсот пятьдесят девять тридцатипятидесятью пятьюдесятью триллионами, тридцатью тримиллионами, пятьсот семьдесят девятьюдесятьюдесятью, двести двадцать восемьмиллионными, сто шестьдесят двумя секстиллиями, пятьсот тысячами, четыре квинтиллиона, двести шестьдесят четыре квадриллиона, триста тридцать семь триллионов пятьсот девяносто три миллиарда пятьсот сорок три миллиона девятьсот пятьдесят тысяч триста тридцать пять долларов США/p >

Ответ 3

Вот модифицированный код, который я использовал:

//Wrapper class for NumberToText(int n) to account for single zero parameter.
public static string ConvertToStringRepresentation(long number)
{
    string result = null;

    if (number == 0)
    {
        result = "Zero";
    }
    else
    {
        result = NumberToText(number);
    }

    return result;
}

//Found at http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,cdceca73-08cd-4c15-aef7-0f9c8096e20a.aspx.
//Modifications from original source:
//  Changed parameter type from int to long.
//  Changed labels to be singulars instead of plurals (Billions to Billion, Millions to Million, etc.).
private static string NumberToText(long 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) + "Hundred " + NumberToText(n % 100);
    else if (n <= 1999)
        return "One Thousand " + NumberToText(n % 1000);
    else if (n <= 999999)
        return NumberToText(n / 1000) + "Thousand " + NumberToText(n % 1000);
    else if (n <= 1999999)
        return "One Million " + NumberToText(n % 1000000);
    else if (n <= 999999999)
        return NumberToText(n / 1000000) + "Million " + NumberToText(n % 1000000);
    else if (n <= 1999999999)
        return "One Billion " + NumberToText(n % 1000000000);
    else
        return NumberToText(n / 1000000000) + "Billion " + NumberToText(n % 1000000000);
}

Ответ 4

public string IntToString(int number)//nobody really uses negative numbers
{
    if(number == 0)
        return "zero";
    else
        if(number == 1)
            return "one";
        .......
        else
            if(number == 2147483647)
                return "two billion one hundred forty seven million four hundred eighty three thousand six hundred forty seven";
}

Ответ 5

Эта тема была большой помощью. Мне нравится решение Райана Эмерле, лучшее для его ясности. Здесь моя версия, которая, я думаю, делает структуру понятной как день:

public static class Number
{
    static string[] first =
    {
        "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine",
        "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen",
        "Seventeen", "Eighteen", "Nineteen"
    };
    static string[] tens =
    {
        "Twenty", "Thirty", "Fourty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety",
    };

    /// <summary>
    /// Converts the given number to an english sentence.
    /// </summary>
    /// <param name="n">The number to convert.</param>
    /// <returns>The string representation of the number.</returns>
    public static string ToSentence(int n)
    {
        return n == 0 ? first[n] : Step(n);
    }
    // traverse the number recursively
    public static string Step(int n)
    {
        return n < 0            ? "Minus " + Step(-n):
               n == 0           ? "":
               n <= 19          ? first[n]:
               n <= 99          ? tens[n / 10 - 2] + " " + Step(n % 10):
               n <= 199         ? "One Hundred " + Step(n % 100):
               n <= 999         ? Step(n / 100) + "Hundred " + Step(n % 100):
               n <= 1999        ? "One Thousand " + Step(n % 1000):
               n <= 999999      ? Step(n / 1000) + "Thousand " + Step(n % 1000):
               n <= 1999999     ? "One Million " + Step(n % 1000000):
               n <= 999999999   ? Step(n / 1000000) + "Million " + Step(n % 1000000):
               n <= 1999999999  ? "One Billion " + Step(n % 1000000000):
                                  Step(n / 1000000000) + "Billion " + Step(n % 1000000000);
    }
}

Ответ 6

Основываясь на решении Райана Эмерле, это добавляет тире в правильные местоположения, не включает в себя конечные пробелы, не плюрализует числа и правильно обрабатывает ввод нуля (0):

public static string ToText(long n) {
    return _toText(n, true);
}
private static string _toText(long n, bool isFirst = false) {
    string result;
    if(isFirst && n == 0) {
        result = "Zero";
    } else if(n < 0) {
        result = "Negative " + _toText(-n);
    } else if(n == 0) {
        result = "";
    } else if(n <= 9) {
        result = new[] { "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine" }[n - 1] + " ";
    } else if(n <= 19) {
        result = new[] { "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen" }[n - 10] + (isFirst ? null : " ");
    } else if(n <= 99) {
        result = new[] { "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety" }[n / 10 - 2] + (n % 10 > 0 ? "-" + _toText(n % 10) : null);
    } else if(n <= 999) {
        result = _toText(n / 100) + "Hundred " + _toText(n % 100);
    } else if(n <= 999999) {
        result = _toText(n / 1000) + "Thousand " + _toText(n % 1000);
    } else if(n <= 999999999) {
        result = _toText(n / 1000000) + "Million " + _toText(n % 1000000);
    } else {
        result = _toText(n / 1000000000) + "Billion " + _toText(n % 1000000000);
    }
    if(isFirst) {
        result = result.Trim();
    }
    return result;
}

Ответ 7

Переход от целого к длинному формату английского языка... Я мог бы написать, что;-) - довольно хорошая статья по теме:

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", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"
        };
    private static string[] groupMapping =
        new string[] {
            "Hundred", "Thousand", "Million", "Billion", "Trillion"
        };

    private static void Main(string[] args) {
        Console.WriteLine(EnglishFromNumber(long.Parse(args[0])));
    }

    private static string EnglishFromNumber(int number) {
        return EnglishFromNumber((long) number);
    }

    private static string EnglishFromNumber(long number) {
        if ( number == 0 ) {
            return onesMapping[number];
        }

        string sign = "Positive";
        if ( number < 0 ) {
            sign = "Negative";
            number = Math.Abs(number);
        }

        string retVal = null;
        int group = 0;
        while(number > 0) {
            int numberToProcess = (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 sign + " " + retVal;
    }

    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 offset

                retVal += ((retVal != null) ? " " : "") + tensMapping[tens];

                if ( ones > 0 ) {
                    retVal += ((retVal != null) ? " " : "") + onesMapping[ones];
                }
            }
        }

        return retVal;
    }
}

Ответ 8

Вот моя уточненная версия первого ответа. Надеюсь, это будет полезно.

/// <summary>
/// Converts an <see cref="int"/> to its textual representation
/// </summary>
/// <param name="num">
/// The number to convert to text
/// </param>
/// <returns>
/// A textual representation of the given number
/// </returns>
public static string ToText(this int num)
{
    StringBuilder result;

    if (num < 0)
    {
        return string.Format("Minus {0}", ToText(-num));
    }

    if (num == 0)
    {
        return "Zero";
    }

    if (num <= 19)
    {
        var oneToNineteen = new[]
        {
            "One",
            "Two",
            "Three",
            "Four",
            "Five",
            "Six",
            "Seven",
            "Eight",
            "Nine",
            "Ten",
            "Eleven",
            "Twelve",
            "Thirteen",
            "Fourteen",
            "Fifteen",
            "Sixteen",
            "Seventeen",
            "Eighteen",
            "Nineteen"
        };

        return oneToNineteen[num - 1];
    }

    if (num <= 99)
    {
        result = new StringBuilder();

        var multiplesOfTen = new[]
        {
            "Twenty",
            "Thirty",
            "Forty",
            "Fifty",
            "Sixty",
            "Seventy",
            "Eighty",
            "Ninety"
        };

        result.Append(multiplesOfTen[(num / 10) - 2]);

        if (num % 10 != 0)
        {
            result.Append(" ");
            result.Append(ToText(num % 10));
        }

        return result.ToString();
    }

    if (num == 100)
    {
        return "One Hundred";
    }

    if (num <= 199)
    {
        return string.Format("One Hundred and {0}", ToText(num % 100));
    }

    if (num <= 999)
    {
        result = new StringBuilder((num / 100).ToText());
        result.Append(" Hundred");
        if (num % 100 != 0)
        {
            result.Append(" and ");
            result.Append((num % 100).ToText());
        }

        return result.ToString();
    }

    if (num <= 999999)
    {
        result = new StringBuilder((num / 1000).ToText());
        result.Append(" Thousand");
        if (num % 1000 != 0)
        {
            switch ((num % 1000) < 100)
            {
                case true:
                    result.Append(" and ");
                    break;
                case false:
                    result.Append(", ");
                    break;
            }

            result.Append((num % 1000).ToText());
        }

        return result.ToString();
    }

    if (num <= 999999999)
    {
        result = new StringBuilder((num / 1000000).ToText());
        result.Append(" Million");
        if (num % 1000000 != 0)
        {
            switch ((num % 1000000) < 100)
            {
                case true:
                    result.Append(" and ");
                    break;
                case false:
                    result.Append(", ");
                    break;
            }

            result.Append((num % 1000000).ToText());
        }

        return result.ToString();
    }

    result = new StringBuilder((num / 1000000000).ToText());
    result.Append(" Billion");
    if (num % 1000000000 != 0)
    {
        switch ((num % 1000000000) < 100)
        {
            case true:
                result.Append(" and ");
                break;
            case false:
                result.Append(", ");
                break;
        }

        result.Append((num % 1000000000).ToText());
    }

    return result.ToString();
}

Ответ 9

В .net нет встроенного решения, но вокруг есть хорошие библиотеки. В настоящее время лучшим является Humanizr:

Console.WriteLine(794663.ToWords()); // => seven hundred and ninety-four thousand six hundred and sixty-three

Он также поддерживает порядковые и римские представления:

Console.WriteLine(794663.ToOrdinalWords()); // => seven hundred and ninety-four thousand six hundred and sixty third
Console.WriteLine(794.ToRoman()); // => DCCXCIV

Humanizr также имеет широкий диапазон инструментов в отношении string, DateTime, TimeSpan и т.д.

Console.WriteLine(794.Seconds().Humanize().Underscore().Hyphenate()); // => 13-minutes

Ответ 10

Другое naasking, версия в VB.NET, если кому-то интересно! Пришлось использовать функцию пола для правильного округления.

 Public Function NumberToText(n As Integer) As String
        Dim a As String() = {"One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"}
        Dim tens As String() = {"Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy",
         "Eighty", "Ninety"}

        If (n < 0) Then
            Return "Minus " + NumberToText(-n)
        ElseIf (n = 0) Then
            Return ""
        ElseIf (n <= 19) Then
            Return a(n - 1) + " "
        ElseIf (n <= 99) Then
            Return tens(Math.Floor(n / 10) - 2) + " " + NumberToText(n Mod 10)
        ElseIf (n <= 199) Then
            Return "One Hundred " + NumberToText(n Mod 100)
        ElseIf (n <= 999) Then
            Return NumberToText(Math.Floor(n / 100)) + "Hundreds " + NumberToText(n Mod 100)
        ElseIf (n <= 1999) Then
            Return "One Thousand " + NumberToText(n Mod 1000)
        ElseIf (n <= 999999) Then
            Return NumberToText(Math.Floor(n / 1000)) + "Thousands " + NumberToText(n Mod 1000)
        ElseIf (n <= 1999999) Then
            Return "One Million " + NumberToText(n Mod 1000000)
        ElseIf (n <= 999999999) Then
            Return NumberToText(Math.Floor(n / 1000000)) + "Millions " + NumberToText(n Mod 1000000)
        ElseIf (n <= 1999999999) Then
            Return "One Billion " + NumberToText(n Mod 1000000000)
        Else
            Return NumberToText(Math.Floor(n / 1000000000)) + "Billions " + NumberToText(n Mod 1000000000)
        End If

    End Function

Ответ 11

Вот более полное/улучшенное решение, основанное на парах идей, также размещенных здесь. Включает исправления грамматики/дефиса и необязательную заглавную букву, длительную поддержку, поддержку нуля и все же очень сжатую (VB.Net):

Function NumberToCapitalizedWords(ByVal n As Long) As String
    Return New System.Globalization.CultureInfo("en-US", False).TextInfo.ToTitleCase(NumberToWords(n))
End Function

Function NumberToWords(ByVal n As Long) As String
    Return LTrim(NumberToWords(n, False, False))
End Function

Function NumberToWords(ByVal n As Long, ByVal recursed As Boolean, ByVal iesLast As Boolean) As String
    If (n < 0) Then
        Return "negative" + NumberToWords(-n, False, False)
    ElseIf (n = 0) Then
        If recursed Then
            Return ""
        End If
        Return "zero"
    ElseIf (n < 20) Then
        Return If(iesLast, "-", " ") + New String() {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"}(n - 1)
    ElseIf (n < 100) Then
        Return " " + New String() {"twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"}(n \ 10 - 2) + NumberToWords(n Mod 10, True, True)
    ElseIf (n < 1000) Then

        Return NumberToWords(n \ 100, True, False) + " hundred" + NumberToWords(n Mod 100, True, False)
    Else
        Dim log1000 As Integer = Math.Floor(Math.Log(n, 1000))
        Return NumberToWords(n \ PowerNoFloat(1000, log1000), True, False) + " " + New String() {"thousand", "million", "billion", "trillion", "quadrillion", "quintillion"}(log1000 - 1) + NumberToWords(n Mod PowerNoFloat(1000, log1000), True, False)
    End If

End Function

Function PowerNoFloat(ByRef base As Long, ByRef power As Integer) As Long
    If power < 0 Then
        Return 0
    End If
    Dim result As Long = 1
    For i As Integer = 1 To power
        result *= base
    Next
    Return result
End Function