Download Source Code
Introduction
Computer programs are best at working with numbers. Working with words requires a bit more work. In some case, you may need to convert numbers to words. For example, a check-writing program needs to write out the check amount using words.
The code presented in this article does just that: It converts a floating-point value to words. The output is suitable for a check-writing program but could easily be adapted for other uses.
Presenting the Code
Listing 1 shows my NumberToText class. It's a simple class with some lookup tables and one method, Convert, which performs the conversion from a Decimal data type to English words.
The Convert method starts by converting the value into a string without the fractional portion. It then loops through the digits in this string in reverse order (the last character to the first).
Scanning the string in reverse order this way allows it to handle special cases. For example, numbers in the teens use two characters for one word. And a number such as 1000, uses one word for all three zeros.
Each time through the loop, the code determines the current column number. From that, it can determine if it is looking at a digit in the ones, tens, or hundreds postion. (After each thousands grouping, it starts again with the ones column.) It uses this information to determine exactly what must be done with the current digit.
Listing 1: The NumberToText Class
namespace NumToText
{
static class NumberToText
{
private static string[] _ones =
{
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine"
};
private static string[] _teens =
{
"ten",
"eleven",
"twelve",
"thirteen",
"fourteen",
"fifteen",
"sixteen",
"seventeen",
"eighteen",
"nineteen"
};
private static string[] _tens =
{
"",
"ten",
"twenty",
"thirty",
"forty",
"fifty",
"sixty",
"seventy",
"eighty",
"ninety"
};
// US Nnumbering:
private static string[] _thousands =
{
"",
"thousand",
"million",
"billion",
"trillion",
"quadrillion"
};
/// <summary>
/// Converts a numeric value to words suitable for the portion of
/// a check that writes out the amount.
/// </summary>
/// <param name="value">Value to be converted</param>
/// <returns></returns>
public static string Convert(decimal value)
{
string digits, temp;
bool showThousands = false;
bool allZeros = true;
// Use StringBuilder to build result
StringBuilder builder = new StringBuilder();
// Convert integer portion of value to string
digits = ((long)value).ToString();
// Traverse characters in reverse order
for (int i = digits.Length - 1; i >= 0; i--)
{
int ndigit = (int)(digits[i] - '0');
int column = (digits.Length - (i + 1));
// Determine if ones, tens, or hundreds column
switch (column % 3)
{
case 0: // Ones position
showThousands = true;
if (i == 0)
{
// First digit in number (last in loop)
temp = String.Format("{0} ", _ones[ndigit]);
}
else if (digits[i - 1] == '1')
{
// This digit is part of "teen" value
temp = String.Format("{0} ", _teens[ndigit]);
// Skip tens position
i--;
}
else if (ndigit != 0)
{
// Any non-zero digit
temp = String.Format("{0} ", _ones[ndigit]);
}
else
{
// This digit is zero. If digit in tens and hundreds
// column are also zero, don't show "thousands"
temp = String.Empty;
// Test for non-zero digit in this grouping
if (digits[i - 1] != '0' || (i > 1 && digits[i - 2] != '0'))
showThousands = true;
else
showThousands = false;
}
// Show "thousands" if non-zero in grouping
if (showThousands)
{
if (column > 0)
{
temp = String.Format("{0}{1}{2}",
temp,
_thousands[column / 3],
allZeros ? " " : ", ");
}
// Indicate non-zero digit encountered
allZeros = false;
}
builder.Insert(0, temp);
break;
case 1: // Tens column
if (ndigit > 0)
{
temp = String.Format("{0}{1}",
_tens[ndigit],
(digits[i + 1] != '0') ? "-" : " ");
builder.Insert(0, temp);
}
break;
case 2: // Hundreds column
if (ndigit > 0)
{
temp = String.Format("{0} hundred ", _ones[ndigit]);
builder.Insert(0, temp);
}
break;
}
}
// Append fractional portion/cents
builder.AppendFormat("and {0:00}/100", (value - (long)value) * 100);
// Capitalize first letter
return String.Format("{0}{1}",
Char.ToUpper(builder[0]),
builder.ToString(1, builder.Length - 1));
}
}
}
Using the Code
Using the code is easy. Convert is a static method so you don't need to create an instance of the class. Just call the Convert method with the value to be converted.
Listing 2: Calling the Convert Method
string result = NumberToText.Convert(12345.67);
Conclusion
I thought this code was kind of interesting. It's a very simple task. Yet, the code ended up getting a little convoluted. It's not a very natural task for a computer to do. But, if needed, it's a handy little routine.
End-User License
Use of this article and any related source code or other files is governed
by the terms and conditions of
.
Author Information
Jonathan Wood
I'm a software/website developer working out of the greater Salt Lake City area in Utah. I've developed many websites including Black Belt Coder, Insider Articles, and others.