Вот неполированный первый выстрел. Нет проверки ошибок вообще, и код не обрабатывает дробную часть. И это почти не проверено. С BigInteger метод может обрабатывать значения до 10^66 - 1
или около 219
битов, легко расширяемых путем добавления дополнительных записей в M2
.
public static String NumberToText(Decimal n)
{
if (n < 0)
{
return "minus " + NumberToText(-n);
}
else if (n == 0)
{
return M1[n];
}
else
{
var scale = 0;
var parts = new List<String>();
while (n != 0)
{
if (n % 1000 != 0)
{
parts.Add(String.Format("{0} {1}", NumberToTextSmaller1000(n % 1000), M2[scale]));
}
n = Math.Floor(n / 1000);
scale++;
}
parts.Reverse();
return String.Join(", ", parts.ToArray());
}
}
private static String NumberToTextSmaller1000(Decimal n)
{
var pattern = (n < 100) ? "{2}" : (n % 100 == 0) ? "{0} {1}" : "{0} {1} {2}";
return String.Format(pattern, M1[Math.Floor(n / 100)], M1[100], NumberToTextSmaller100(n % 100));
}
private static String NumberToTextSmaller100(Decimal n)
{
return (0 <= n) && (n < 20)) || (n % 10 == 0)
? M1[n]
: String.Format("{0}-{1}", M1[n - n % 10], M1[n % 10];
}
private static readonly IDictionary<Decimal, String> M1 = new Dictionary<Decimal, String>
{
{ 0, "zero" }, { 1, "one" }, { 2, "two" }, { 3, "three" },
{ 4, "four" }, { 5, "five" }, { 6, "six" }, { 7, "seven" },
{ 8, "eight" }, { 9, "nine" }, { 10, "ten" }, { 11, "eleven" },
{ 12, "twelve" }, { 13, "thirteen" }, { 14, "fourteen" },
{ 15, "fifteen" }, { 16, "sixteen" }, { 17, "seventeen" },
{ 18, "eighteen" }, { 19, "nineteen" }, { 20, "twenty" },
{ 30, "thirty" }, { 40, "forty" }, { 50, "fifty" }, { 60, "sixty" },
{ 70, "seventy" }, { 80, "eighty" }, { 90, "ninety" }, { 100, "hundred" }
};
// The leading spaces are important.
private static readonly IDictionary<Decimal, String> M2 = new Dictionary<Decimal, String>
{
{ 0, String.Empty }, { 1, " thousand" }, { 2, " million" }, { 3, " billion" },
{ 4, " trillion" }, { 5, " quadrillion" }, { 6, " quintillion" },
{ 7, " sextillion" }, { 8, " septillion" }, { 9, " octillion" },
{ 10, " nonillion" }, { 11, " decillion" }, { 12, " undecillion" },
{ 13, " duodecillion" }, { 14, " tredecillion" }, { 15, " quattuordecillion" },
{ 16, " quindecillion" }, { 17, " sexdecillion" }, { 18, " septendecillion" },
{ 19, " octodecillion" }, { 20, " novemdecillion" }, { 21, " vigintillion" }
};
При вызове Decimal.MaxValue
метод возвращает следующее.
семьдесят девять октиллионов, двести двадцать восемь септиллионов, сто шестьдесят два секстиллиона, пятьсот четырнадцать квинтиллионов, двести шестьдесят четыре квадриллиона, триста тридцать семь триллионов пятьсот девяносто три миллиарда пятьсот сорок три миллиона девятьсот пятьдесят тысяч триста тридцать пять