Last active
December 12, 2015 05:28
-
-
Save slaneyrw/4721445 to your computer and use it in GitHub Desktop.
Convert a text representing a number to a currency word version.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class NumberWordConverter | |
{ | |
#region Lookups | |
private static readonly Dictionary<char, string> units = new Dictionary<char, string>() | |
{ | |
{'0', ""}, | |
{'1', " One"}, | |
{'2', " Two"}, | |
{'3', " Three"}, | |
{'4', " Four"}, | |
{'5', " Five"}, | |
{'6', " Six"}, | |
{'7', " Seven"}, | |
{'8', " Eight"}, | |
{'9', " Nine"}, | |
}; | |
private static readonly Dictionary<char, string> tens = new Dictionary<char, string>() | |
{ | |
{'0', ""}, | |
{'1', " Ten"}, | |
{'2', " Twenty"}, | |
{'3', " Thirty"}, | |
{'4', " Forty"}, | |
{'5', " Fifty"}, | |
{'6', " Sixty"}, | |
{'7', " Seventy"}, | |
{'8', " Eighty"}, | |
{'9', " Ninety"}, | |
}; | |
private static readonly Dictionary<char, string> teens = new Dictionary<char, string>() | |
{ | |
{'0', " Ten"}, | |
{'1', " Eleven"}, | |
{'2', " Twelve"}, | |
{'3', " Thirteen"}, | |
{'4', " Fourteen"}, | |
{'5', " Fiveteen"}, | |
{'6', " Sixteen"}, | |
{'7', " Seventeen"}, | |
{'8', " Eighteen"}, | |
{'9', " Nineteen"}, | |
}; | |
private static readonly string[] numberScales = new string[] | |
{ | |
"", | |
" Thousand", | |
" Million", | |
" Billion", | |
" Trillion", | |
" Quadrillion", | |
" Quintillion", | |
" Sextillion", | |
" Septillion" | |
}; | |
#endregion | |
public static string ToCurrencyWords(this string text, string major = "Dollars", string minor = "Cents", int minorSize = 2) | |
{ | |
string[] parts = (text + ".00").Split('.'); // Forces all numbers to #.00 format. | |
// If supplied number contained a fraction, then the split array now contain | |
// 3 elements so will ignore our extra addition. | |
// Force fractional parts to 1 extra decimal places then round away from zero | |
parts[1] = Math | |
.Round(int.Parse(parts[1].PadRight(minorSize + 1, '0').Substring(0, minorSize + 1)) / 10d, MidpointRounding.AwayFromZero) | |
.ToString(CultureInfo.InvariantCulture); | |
string majorText = parts[0].ToNumber(major); | |
string minorText = parts[1].ToNumber(minor); | |
return majorText | |
+ (majorText.Length > 0 && minorText.Length > 0 ? " and " : "") | |
+ minorText; | |
} | |
public static string ToNumber(this string text, string postFix) | |
{ | |
int length = text.Length + (3 - text.Length%3)%3; | |
Stack<char> chars = new Stack<char>(text.PadLeft(length, '0').ToCharArray()); | |
Queue<string> modifiers = new Queue<string>(numberScales); | |
string result = string.Empty; | |
while (chars.Count > 0) | |
{ | |
result = ConvertTriad(chars.Pop(), chars.Pop(), chars.Pop(), modifiers.Dequeue(), chars.Count > 0) + result; | |
} | |
return (string.IsNullOrWhiteSpace(result) ? string.Empty : result.Trim() + " " + postFix); | |
} | |
private static string ConvertTriad(char unit, char ten, char hundred, string modifier, bool hasMore) | |
{ | |
string result = ""; | |
string tempModifier = string.Empty; // In the case all 3 chars are '0' we skip this level | |
if (hundred != '0') | |
{ | |
result = units[hundred] + " hundred"; | |
tempModifier = modifier; // Have a hundred number, restore the modifier in case no tens or units | |
} | |
if (ten == '0' && unit == '0') | |
return result + tempModifier; | |
if (!string.IsNullOrEmpty(result) || hasMore) | |
result += " and"; | |
return result + ((ten == '1') ? teens[unit] : tens[ten] + units[unit]) + modifier; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment