public static void Main()
Test(2, Currency.NZD, "Two dollars.");
Test(5, Currency.NZD, "Five dollars.");
Test(5.20m, Currency.NZD, "Five dollars and twenty cents.");
Test(10.01m, Currency.NZD, "Ten dollars and one cent.");
Test(8m, Currency.GBP, "Eight pounds.");
Test(100, Currency.NZD, "One hundred dollars.");
Test(10.5m, Currency.GBP, "Ten pounds and fifty pence.");
static string CurrencyInWords(decimal amount, Currency currency)
var builder = new StringBuilder();
MaybeAddWholeAmountWords(builder, amount, currency);
MaybeAddFactionalAmountWords(builder, amount, currency);
return builder.ToString();
private static void MaybeAddWholeAmountWords(StringBuilder builder, decimal amount, Currency currency) {
builder.Append(((int)amount).ToWords().Humanize());
builder.Append($" {currency.Word}s");
private static void MaybeAddFactionalAmountWords(StringBuilder builder, decimal amount, Currency currency) {
var fractionAmount = (int)((amount - (int)amount) * 100m);
builder.Append(fractionAmount.ToWords());
if (currency == Currency.GBP) {
builder.Append(" pence");
public static readonly Currency NZD = new Currency("NZD", "dollar");
public static readonly Currency GBP = new Currency("GBP", "pound");
public string Symbol { get; }
public string Word { get; }
Currency(string symbol, string word)
static void Test(decimal amount, Currency currency, string expected)
Console.WriteLine($"Test: {amount}, {currency}, {expected}");
actual = CurrencyInWords(amount, currency);
Console.WriteLine("PASS.\n");
actual = "Exception: " + e.Message;
Console.WriteLine("FAIL:");
Console.WriteLine(" Expected: " + expected);
Console.WriteLine(" Actual : " + actual);
Console.WriteLine($"{pass} / {pass + fail} tests passed.\n");
Console.WriteLine(fail == 0 ? "SUCCESS!" : "FAILURE!");