Files
ROLAC/API/ROLAC.API/Services/Disbursement/AmountToWords.cs
T
Chris Chen 3558c67fd7 WIP
2026-06-20 17:51:33 -07:00

76 lines
2.4 KiB
C#

namespace ROLAC.API.Services.Disbursement;
/// <summary>
/// Converts a monetary amount to the English words used on a check, e.g.
/// 1234.56 → "One Thousand Two Hundred Thirty-Four and 56/100 Dollars".
/// Pure and dependency-free so it is easily unit-tested.
/// </summary>
public static class AmountToWords
{
private static readonly string[] Ones =
[
"Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine",
"Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen",
"Seventeen", "Eighteen", "Nineteen",
];
private static readonly string[] Tens =
[
"", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety",
];
// index 1.. → 10^(3*index)
private static readonly string[] Scales = ["", "Thousand", "Million", "Billion", "Trillion"];
public static string Convert(decimal amount)
{
if (amount < 0) amount = 0m;
// Round half-up to cents.
amount = Math.Round(amount, 2, MidpointRounding.AwayFromZero);
var dollars = (long)Math.Floor(amount);
var cents = (int)Math.Round((amount - dollars) * 100m, MidpointRounding.AwayFromZero);
var words = dollars == 0 ? "Zero" : ThreeDigitGroupsToWords(dollars);
return $"{words} and {cents:00}/100 Dollars";
}
private static string ThreeDigitGroupsToWords(long n)
{
// Split into groups of three digits, low to high.
var groups = new List<int>();
while (n > 0) { groups.Add((int)(n % 1000)); n /= 1000; }
var parts = new List<string>();
for (var i = groups.Count - 1; i >= 0; i--)
{
if (groups[i] == 0) continue;
var group = HundredsToWords(groups[i]);
var scale = Scales[i];
parts.Add(string.IsNullOrEmpty(scale) ? group : $"{group} {scale}");
}
return string.Join(" ", parts);
}
private static string HundredsToWords(int n)
{
var parts = new List<string>();
if (n >= 100)
{
parts.Add($"{Ones[n / 100]} Hundred");
n %= 100;
}
if (n >= 20)
{
var t = Tens[n / 10];
var o = n % 10;
parts.Add(o == 0 ? t : $"{t}-{Ones[o]}");
}
else if (n > 0)
{
parts.Add(Ones[n]);
}
return string.Join(" ", parts);
}
}