Task

Show how to spell out a number in English.

You can use a preexisting implementation or roll your own, but you should support inputs up to at least one million (or the maximum value of your language's default bounded integer type, if that's less).

Support for inputs other than positive integers (like zero, negative integers, and floating-point numbers) is optional.



Related task

   Spelling of ordinal numbers.


#!/usr/local/bin/shale
 
maths library
 
0 ones:: dup var "zero" =
1 ones:: dup var "one" =
2 ones:: dup var "two" =
3 ones:: dup var "three" =
4 ones:: dup var "four" =
5 ones:: dup var "five" =
6 ones:: dup var "six" =
7 ones:: dup var "seven" =
8 ones:: dup var "eight" =
9 ones:: dup var "nine" =
10 teens:: dup var "ten" =
11 teens:: dup var "eleven" =
12 teens:: dup var "twelve" =
13 teens:: dup var "thirteen" =
14 teens:: dup var "fourteen" =
15 teens:: dup var "fifteen" =
16 teens:: dup var "sixteen" =
17 teens:: dup var "seventeen" =
18 teens:: dup var "eighteen" =
19 teens:: dup var "nineteen" =
2 tens:: dup var "twenty" =
3 tens:: dup var "thirty" =
4 tens:: dup var "forty" =
5 tens:: dup var "fifty" =
6 tens:: dup var "sixty" =
7 tens:: dup var "seventy" =
8 tens:: dup var "eighty" =
9 tens:: dup var "ninety" =
 
say dup var {
  commaFlag dup var swap =
  andFlag dup var swap =
  n dup var swap =
  h dup var n 100 / =
  t dup var n 100 % =
  o dup var n 10 % =
 
  h 0 > {
    commaFlag { "," print commaFlag false = } ifthen
    h.value ones:: " %s hundred" printf
  } ifthen
 
  h 0 > t 0 > and t 0 > andFlag and or { " and" print commaFlag false = } ifthen
 
  t 9 > {
    t 19 > {
      commaFlag { "," print commaFlag false = } ifthen
      t 10 / tens:: " %s" printf
      o 0 > { o.value ones:: "-%s" printf } ifthen
    } {
      t 9 > { commaFlag { "," print } ifthen t.value teens:: " %s" printf } ifthen
    } if
  } {
    o 0 > { commaFlag { "," print } ifthen o.value ones:: " %s" printf } ifthen
  } if
} =
 
speak dup var {
  n dup var swap =
  m dup var n 1000000 / =
  t dup var n 1000 /  1000 % =
  h dup var n 1000 % =
 
  n "%10d ->" printf
  m 0 > { m.value false false say() " million" print } ifthen
  t 0 > { t.value false m 0 > say() " thousand" print } ifthen
  h 0 > m 0 == t 0 == and or { h.value m 0 > t 0 > or dup say() } ifthen
  "" println
} =
 
"Stock numbers" println
1 speak()
10 speak()
100 speak()
1000 speak()
1001 speak()
100001000 speak()
100001001 speak()
123456789 speak()
987654321 speak()
100200300 speak()
10020030 speak()
 
"" println
"Randomly generated numbers" println
i var
i 0 =
{ i 10 < } {
  random maths::() 1000000000 % speak()   // Cap it to less than 1 billion.
  i++
} while