Why stop at 1-9...
C#'s version of the way Squeak Smalltalk does it for all numbers to a vigintillion:
public static String AsWords(this int aNumber) {
var answer = "";
if (aNumber == 0) return "zero";
if (aNumber < 0) {
answer = "negative";
aNumber = Math.Abs(aNumber);
}
var thousands = new[] {"", "thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion", "septillion","octillion", "nonillion", "decillion", "undecillion", "duodecillion", "tredecillion", "quattuordecillion", "quindecillion", "sexdecillion", "septendecillion", "octodecillion", "novemdecillion", "vigintillion"};
var thousandCount = 0;
while (aNumber > 0) {
var underOneThousandName = ThreeDigitName(aNumber % 1000);
aNumber = aNumber / 1000;
if(underOneThousandName != "") {
if (answer != "") answer = "," + answer;
answer = underOneThousandName + " " + thousands[thousandCount] + answer;
}
thousandCount += 1;
}
return answer;
}
private static string ThreeDigitName(int aNumberLessThanOneThousand) {
if (aNumberLessThanOneThousand == 0) return "";
var units = new[] {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eightteen", "nineteen"};
var answer = "";
if (aNumberLessThanOneThousand > 99) {
answer = units[(aNumberLessThanOneThousand / 100) - 1] + " hundred";
if (aNumberLessThanOneThousand % 100 != 0)
answer += " " + ThreeDigitName(aNumberLessThanOneThousand % 100);
return answer;
}
if (aNumberLessThanOneThousand < 20) return units[aNumberLessThanOneThousand -1];
var multiplesOfTen = new[] {"twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
answer += multiplesOfTen[(aNumberLessThanOneThousand / 10)-2];
if (aNumberLessThanOneThousand % 10 != 0) answer += "-" + units[(aNumberLessThanOneThousand % 10)-1];
return answer;
}