示例输入:
4,567,788
示例输出:
四百五十六万七千七百八十八
目前最好、最强大的库,肯定是 Humanizer。它是开源的,并且作为 NuGet 包可用:
Console.WriteLine(4567788.ToWords()); // => four million five hundred and sixty-seven thousand seven hundred and eighty-eight
Console.WriteLine(4567788.ToOrdinalWords().Underscore().Hyphenate().ApplyCase(LetterCasing.AllCaps)); // => FOUR-MILLION-FIVE-HUNDRED-AND-SIXTY-SEVEN-THOUSAND-SEVEN-HUNDRED-AND-EIGHTY-EIGHTH
如果您使用在将数字转换为单词C#中找到的代码,并且您需要用于十进制数,以下是如何操作:
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;
}
一个完全递归的版本:
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();
}
目前它可以处理(短刻度)万亿级别的数字。只需更改thous
变量,即可添加对更大数字或长刻度的支持。
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();
}
}
关键在于最后一个 ToWords
重载函数。
西班牙语版本:
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;
}
JavaScript版本:
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();
}
我使用C#创建了一个Web API,可以将数字转换为文字。
输入可以是48小时时间格式的整数或带小数点的数字。
调用来自前端应用程序,使用Ajax Post方法,并在网页中返回转换后的结果。
我在GitHub上分享了这个项目:https://github.com/marvinglennlacuna/NumbersToWordsConverter.Api
以下是技术实现:
并且有关以下内容的技术文档:
通过网页返回结果(US-001)
US-001 通过网页将数字转换为文字的过程
US-001 通过网页输出将数字转换为文字
通过 Postman 返回结果(US-002)
US-002 - 通过 Postman 进程将数字转换为单词
US-002 - 通过 Postman 输出将数字转换为单词
我编写了一个C#函数NumIntToWords(String NumIn)
,它提供了一种简单、短小、高效的方法来将整数转换为英文单词,符合美式英语语法规则。
该函数使用了我设计的SLST(Single Loop String Triplet)方法。
与我在这里和其他地方看到的其他方法不同,该函数具有以下特点:
我选择将要转换的整数作为字符串传递,以便您可以轻松处理非常大的整数。
您可以像这样使用它:
Console.WriteLine(NumIntToWords("1991345678974"));
输出:
一万九千九百九十一亿三千四百五十六万七千八百九十四
C# SLST函数方法(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
}
http://www.exchangecore.com/blog/convert-number-words-c-sharp-console-application/提供了一些C#脚本,看起来可以处理非常大的数字和非常小的小数。
using System;
using System.Collections.Generic;
using System.Text;
namespace NumWords
{
class Program
{
// PROGRAM HANDLES NEGATIVE AND POSITIVE DOUBLES
static String NumWordsWrapper(double n)
{
string words = "";
double intPart;
double decPart = 0;
if (n == 0)
return "zero";
try {
string[] splitter = n.ToString().Split('.');
intPart = double.Parse(splitter[0]);
decPart = double.Parse(splitter[1]);
} catch {
intPart = n;
}
words = NumWords(intPart);
if (decPart > 0) {
if (words != "")
words += " and ";
int counter = decPart.ToString().Length;
switch (counter) {
case 1: words += NumWords(decPart) + " tenths"; break;
case 2: words += NumWords(decPart) + " hundredths"; break;
case 3: words += NumWords(decPart) + " thousandths"; break;
case 4: words += NumWords(decPart) + " ten-thousandths"; break;
case 5: words += NumWords(decPart) + " hundred-thousandths"; break;
case 6: words += NumWords(decPart) + " millionths"; break;
case 7: words += NumWords(decPart) + " ten-millionths"; break;
}
}
return words;
}
static String NumWords(double n) //converts double to words
{
string[] numbersArr = new string[] { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
string[] tensArr = new string[] { "twenty", "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninty" };
string[] suffixesArr = new string[] { "thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion", "septillion", "octillion", "nonillion", "decillion", "undecillion", "duodecillion", "tredecillion", "Quattuordecillion", "Quindecillion", "Sexdecillion", "Septdecillion", "Octodecillion", "Novemdecillion", "Vigintillion" };
string words = "";
bool tens = false;
if (n < 0) {
words += "negative ";
n *= -1;
}
int power = (suffixesArr.Length + 1) * 3;
while (power > 3) {
double pow = Math.Pow(10, power);
if (n >= pow) {
if (n % pow > 0) {
words += NumWords(Math.Floor(n / pow)) + " " + suffixesArr[(power / 3) - 1] + ", ";
} else if (n % pow == 0) {
words += NumWords(Math.Floor(n / pow)) + " " + suffixesArr[(power / 3) - 1];
}
n %= pow;
}
power -= 3;
}
if (n >= 1000) {
if (n % 1000 > 0) words += NumWords(Math.Floor(n / 1000)) + " thousand, ";
else words += NumWords(Math.Floor(n / 1000)) + " thousand";
n %= 1000;
}
if (0 <= n && n <= 999) {
if ((int)n / 100 > 0) {
words += NumWords(Math.Floor(n / 100)) + " hundred";
n %= 100;
}
if ((int)n / 10 > 1) {
if (words != "")
words += " ";
words += tensArr[(int)n / 10 - 2];
tens = true;
n %= 10;
}
if (n < 20 && n > 0) {
if (words != "" && tens == false)
words += " ";
words += (tens ? "-" + numbersArr[(int)n - 1] : numbersArr[(int)n - 1]);
n -= Math.Floor(n);
}
}
return words;
}
static void Main(string[] args)
{
Console.Write("Enter a number to convert to words: ");
Double n = Double.Parse(Console.ReadLine());
Console.WriteLine("{0}", NumWordsWrapper(n));
}
}
}
编辑:从博客文章中带来了代码
更详细的功能实现:
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;
}
}
我使用的字符串插值仅在4.6.1版本中可用。