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.");
Test(1, Currency.NZD, "One dollar.");
Test(57m, Currency.JPY, "Fifty-seven yen.");
Test(57.6m, Currency.JPY, "Fifty-seven yen.");
Test(0.10m, Currency.NZD, "Zero dollars and ten cents.");
Test(0, Currency.NZD, "Zero dollars.");
Test(0.9999999999m, Currency.NZD, "One dollar.");
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) {
var wholeAmount = (int)amount;
builder.Append(wholeAmount.ToWords().Transform(To.SentenceCase));
if(wholeAmount > 1 || wholeAmount < 1)
builder.Append(currency.PluralisedWord());
builder.Append(currency.Word);
private static void MaybeAddFactionalAmountWords(StringBuilder builder, decimal amount, Currency currency) {
if(!currency.SupportsFractionalAmounts())
var fractionAmount = (int)((amount - (int)amount) * 100m);
builder.Append(fractionAmount.ToWords());
if(fractionAmount > 1 && currency != Currency.GBP)
builder.AppendFormat(" {0}", currency.SmallerWord.ToString().Pluralize());
builder.AppendFormat(" {0}", currency.SmallerWord.ToString());
public static readonly Currency NZD = new Currency("NZD", "dollar", "cent");
public static readonly Currency GBP = new Currency("GBP", "pound", "pence");
public static readonly Currency JPY = new Currency("JPY", "yen", "");
public string Symbol { get; }
public string Word { get; }
public string SmallerWord { get; }
public bool SupportsFractionalAmounts() {
return SmallerWord != "";
public string PluralisedWord() {
return Symbol == "JPY" ? Word : Word.Pluralize();
Currency(string symbol, string word, string smallerWord)
SmallerWord = smallerWord;
static void Test(decimal amount, Currency currency, string expected)
Console.WriteLine($"Test: {amount}, {currency.Symbol}, {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!");