cardinal.rkt
```#lang racket/base

(require racket/contract)

;; A library for computing the English cardinal number string
;; representations.
;;
;; http://en.wikipedia.org/wiki/Names_of_numbers_in_English

(provide

(contract-out
[number->cardinal [countable-number? . -> . string?]])

(rename-out [number->cardinal number->cardinal/uncontracted])

maximum-countable-cardinal-number)

;; countable-number? any -> boolean
(define (countable-number? n)
(and (exact-nonnegative-integer? n)
(<= n maximum-countable-cardinal-number)))

;; number->cardinal: number -> string
;; Converts the number to a string.
;;
;; TODO: we should do efficient string concatenation if profiling demands it.
;;
(define (number->cardinal n)
(cond
[(< n 1000)
(small-number->cardinal n)]
[else
(define this-mag (mag10 n))
(cond
[(>= this-mag max-mag)
(error 'number->cardinal "~s too large to count" n)]
[else
(define s (quotient this-mag 3))
(define t (expt 10 (* 3 s)))
(if (= 0 (remainder n t))
(string-append (small-number->cardinal (quotient n t))
" "
(vector-ref scales s))
(string-append (small-number->cardinal (quotient n t))
" " (vector-ref scales s)
" " (number->cardinal (remainder n t))))])]))

;; Handles numbers between 0 and 999.
(define (small-number->cardinal n)
(cond
[(< n 21)
(vector-ref small-cardinals n)]
[(< n 100)
(if (= 0 (remainder n 10))
(vector-ref tens (quotient n 10))
(string-append (vector-ref tens (quotient n 10))
"-"
(vector-ref small-cardinals (remainder n 10))))]
[(< n 1000)
(if (= 0 (remainder n 100))
(string-append (small-number->cardinal (quotient n 100))
" hundred")
(string-append (small-number->cardinal (quotient n 100))
" hundred "
(small-number->cardinal (remainder n 100))))]))

(define small-cardinals #("zero" "one" "two" "three" "four"
"five" "six" "seven" "eight" "nine" "ten"
"eleven" "twelve" "thirteen" "fourteen"
"fifteen" "sixteen" "seventeen" "eighteen"
"nineteen" "twenty"))

(define tens #(""
"ten" "twenty" "thirty" "forty"
"fifty" "sixty" "seventy" "eighty"
"ninety"))

;; http://www.mrob.com/pub/math/largenum.html
(define scales
#(""
"thousand"       ;; 10^3
"million"        ;; 10^6
"billion"        ;; 10^9
"trillion"       ;; 10^12
"quintillion"    ;; ...
"sextillion"
"septillion"
"octillion"
"nonillion"
"decillion"
"undecillion"
"duodecillion"
"tredecillion"
"quattuordecillion"
"quindecillion"
"sexdecillion"
"septendecillion"
"octodecillion"
"novemdecillion"
"vigintillion"
))

;; Porduces the magnitude of a number in terms of powers of 10.
(define (mag10 n)
(let loop ([n n]
[x 0])
(cond [(= 0 (quotient n 10))
x]
[else
(loop (quotient n 10)