Number names: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|REXX}}: added REXX code.)
m (→‎{{header|REXX}}: corrected the number of digits supported.)
Line 1,729: Line 1,729:
* currency symbols
* currency symbols
* adding commas (or whatever) to the output (including blanks)
* adding commas (or whatever) to the output (including blanks)
* numbers (American) up to 302 digits, (English) up to 602 digits
* numbers (American) up to 3,000 digits, (English) up to 6,000 digits
* numbers with suffixes such as K, M, Gi, etc, and also some common ones as well as factorials
* numbers with suffixes such as K, M, Gi, etc, and also some common ones as well as factorials
* user-defineable names for: signs, decimal point, power, curreny symbols, zero (digit), etc.
* user-defineable names for: signs, decimal point, power, curreny symbols, zero (digit), etc.
Line 1,751: Line 1,751:
number of names (instead of having a fixed amount of names in text form).
number of names (instead of having a fixed amount of names in text form).
</pre>
</pre>
===REXX program===
<pre style="height:30ex;overflow:scroll">
<pre style="height:30ex;overflow:scroll">
/**/trace o;parse arg !;if !all(arg()) then exit;if !cms then address '';signal on halt;signal on novalue;signal on syntax
/**/trace o;parse arg !;if !all(arg()) then exit;if !cms then address '';signal on halt;signal on novalue;signal on syntax
Line 2,182: Line 2,183:
sp:!call=']'!fn;sp="$SPELL#"(arg(1) 'Q');!call=;return sp
sp:!call=']'!fn;sp="$SPELL#"(arg(1) 'Q');!call=;return sp
syntax:!sigl=sigl;call er 13,!fid(2) !fid(3) !sigl !cal() condition('D') sourceline(!sigl)
syntax:!sigl=sigl;call er 13,!fid(2) !fid(3) !sigl !cal() condition('D') sourceline(!sigl)
</pre>
===output===
<pre style="height:30ex;overflow:scroll">
Output when using the input of: 373 ordinal
three hundred seventy-third

Output when using the input of: 373
three hundred seventy-three

Output when using the input of: +45
plus forty-five

Output when using the input of: 1989 asYear
nineteen eighty-nine

Output when using the input of: -12.79
minus twelve point seven nine

Output when using the input of: $119.63
one hundred nineteen dollars and sixty-three cents

Output when using the input of: 3456T
three quadrillion four hundred fifty-six trillion

Output when using the input of: 4Ki
four thousand ninety-six

Output when using the input of: 6!
seven hundred twenty

Output when using the input of: 10dozen
one hundred twenty

Output when using the input of: 70000000000000...(3,000 zeroes total)
seven octononagintanongentillion
</pre>
</pre>



Revision as of 00:09, 16 December 2010

Task
Number names
You are encouraged to solve this task according to the task description, using any language you may know.

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.

Ada

<lang ada>with Ada.Text_IO; use Ada.Text_IO;

procedure Integers_In_English is

  type Spellable is range 0..999_999_999_999_999_999;
  function Spell (N : Spellable) return String is
     function Twenty (N : Spellable) return String is
     begin
        case N mod 20 is
           when  0 => return "zero";
           when  1 => return "one";
           when  2 => return "two";
           when  3 => return "three";
           when  4 => return "four";
           when  5 => return "five";
           when  6 => return "six";
           when  7 => return "seven";
           when  8 => return "eight";
           when  9 => return "nine";
           when 10 => return "ten";
           when 11 => return "eleven";
           when 12 => return "twelve";
           when 13 => return "thirteen";
           when 14 => return "fourteen";
           when 15 => return "fifteen";
           when 16 => return "sixteen";
           when 17 => return "seventeen";
           when 18 => return "eighteen";
           when others => return "nineteen";
        end case;
     end Twenty;
     function Decade (N : Spellable) return String is
     begin
        case N mod 10 is
           when 2 => return "twenty";
           when 3 => return "thirty";
           when 4 => return "forty";
           when 5 => return "fifty";
           when 6 => return "sixty";
           when 7 => return "seventy";
           when 8 => return "eighty";
           when others => return "ninety";
        end case;
     end Decade;
     function Hundred (N : Spellable) return String is
     begin
        if N < 20 then
           return Twenty (N);
        elsif 0 = N mod 10 then
           return Decade (N / 10 mod 10);
        else
           return Decade (N / 10) & '-' & Twenty (N mod 10);
        end if;
     end Hundred;
     function Thousand (N : Spellable) return String is
     begin
        if N < 100 then
           return Hundred (N);
        elsif 0 = N mod 100 then
           return Twenty (N / 100) & " hundred";
        else
           return Twenty (N / 100) & " hundred and " & Hundred (N mod 100);
        end if;
     end Thousand;
     function Triplet
              (  N     : Spellable;
                 Order : Spellable;
                 Name  : String;
                 Rest  : not null access function (N : Spellable) return String
              )  return String is
        High : Spellable := N / Order;
        Low  : Spellable := N mod Order;
     begin
        if High = 0 then
           return Rest (Low);
        elsif Low = 0 then
           return Thousand (High) & ' ' & Name;
        else
           return Thousand (High) & ' ' & Name & ", " & Rest (Low);
        end if;
     end Triplet;
     function Million (N : Spellable) return String is
     begin
        return Triplet (N, 10**3, "thousand", Thousand'Access);
     end Million;
     function Milliard (N : Spellable) return String is
     begin
        return Triplet (N, 10**6, "million", Million'Access);
     end Milliard;
     function Billion (N : Spellable) return String is
     begin
        return Triplet (N, 10**9, "milliard", Milliard'Access);
     end Billion;
     function Billiard (N : Spellable) return String is
     begin
        return Triplet (N, 10**12, "billion", Billion'Access);
     end Billiard;
  begin
     return Triplet (N, 10**15, "billiard", Billiard'Access);
  end Spell;

begin

  Put_Line ("               99 " & Spell (               99));
  Put_Line ("              300 " & Spell (              300));
  Put_Line ("              310 " & Spell (              310));
  Put_Line ("            1_501 " & Spell (            1_501));
  Put_Line ("           12_609 " & Spell (           12_609));
  Put_Line ("          512_609 " & Spell (          512_609));
  Put_Line ("       43_112_609 " & Spell (       43_112_609));
  Put_Line ("   77_000_112_609 " & Spell (   77_000_112_609));
  Put_Line ("2_000_000_000_100 " & Spell (2_000_000_000_100));

end Integers_In_English;</lang> The solution is recursive by the triplets of decimal numbers. The implementation goes up to 1018-1. Sample output:

               99 ninety-nine
              300 three hundred
              310 three hundred and ten
            1_501 one thousand, five hundred and one
           12_609 twelve thousand, six hundred and nine
          512_609 five hundred and twelve thousand, six hundred and nine
       43_112_609 forty-three million, one hundred and twelve thousand, six hundred and nine
   77_000_112_609 seventy-seven milliard, one hundred and twelve thousand, six hundred and nine
2_000_000_000_100 two billion, one hundred

ALGOL 68

Works with: ALGOL 68 version Standard - no extensions to language used
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny
Works with: ELLA ALGOL 68 version Any (with appropriate job cards) - tested with release 1.8.8d.fc9.i386

<lang algol68>PROC number words = (INT n)STRING:(

 # returns a string representation of n in words. Currently
 deals with anything from 0 to 999 999 999. #
   []STRING digits = []STRING
     ("zero","one","two","three","four","five","six","seven","eight","nine")[@0];
   []STRING teens = []STRING
     ("ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen")[@0];
   []STRING decades = []STRING
     ("twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety")[@2];

   PROC three digits = (INT n)STRING: (
     # does the conversion for n from 0 to 999. #
       INT tens = n MOD 100 OVER 10;
       INT units = n MOD 10;
       (n >= 100|digits[n OVER 100] + " " + "hundred" + (n MOD 100 /= 0|" and "|"")|"") +
       (tens /= 0|(tens = 1|teens[units]|decades[tens] + (units /= 0|"-"|""))|"") +
       (units /= 0 AND tens /= 1 OR n = 0|digits[units]|"")
     );
   INT m = n OVER 1 000 000;
   INT k = n MOD 1 000 000 OVER 1000;
   INT u = n MOD 1000;
   (m /= 0|three digits(m) + " million"|"") +
   (m /= 0 AND (k /= 0 OR u >= 100)|", "|"") +
   (k /= 0|three digits(k) + " thousand"|"") +
   ((m /= 0 OR k /= 0) AND u > 0 AND u < 100|" and " |: k /= 0 AND u /= 0|", "|"") +
   (u /= 0 OR n = 0|three digits(u)|"")
 );

on logical file end(stand in, (REF FILE f)BOOL: GOTO stop iteration); on value error(stand in, (REF FILE f)BOOL: GOTO stop iteration); DO # until user hits EOF #

 INT n;
 print("n? ");
 read((n, new line));
 print((number words(n), new line))

OD; stop iteration:

 SKIP</lang>

Example input with output:

n? 43112609
forty-three million, one hundred and twelve thousand, six hundred and nine
Translation of: Python
Works with: ALGOL 68 version Standard - no extensions to language used - note size of LONG LONG INT is implementation specific
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny

<lang Algol68>MODE EXCEPTION = STRUCT(STRING name, PROC VOID handler); EXCEPTION value error = ("Value Error", stop);

PROC raise = (EXCEPTION exception, STRING str error)VOID: (

 put(stand error, (name OF exception,": ",str error, new line));
 handler OF exception

);

MODE LINT = LONG LONG INT;

BOOL locale euro := TRUE;

PROC spell integer = (LINT n)STRING: (

   []STRING tens = []STRING (~, ~, "twenty", "thirty", "forty",
           "fifty", "sixty", "seventy", "eighty", "ninety")[@0];

   []STRING small = []STRING ("zero", "one", "two", "three", "four", "five",
            "six", "seven", "eight", "nine", "ten", "eleven",
            "twelve", "thirteen", "fourteen", "fifteen",
            "sixteen", "seventeen", "eighteen", "nineteen")[@0];

   []STRING bl = []STRING (~, ~, "m", "b", "tr", "quadr",
         "quint", "sext", "sept", "oct", "non", "dec")[@0];

   PROC nonzero = (STRING c, LINT n)STRING:
       IF n = 0 THEN "" ELSE c + spell integer(n) FI;

   PROC big =(INT e, LINT n)STRING:
       spell integer(n) + 
       CASE e+1 IN
       #0# "", 
       #1# " thousand"
       OUT
           " " + 
           IF locale euro THEN # handle millard, billard & trillard etc #
             bl[e OVER 2 + 1 ]+"ill" + CASE e MOD 2 IN "ard" OUT "ion" ESAC
           ELSE 
             bl[e]+"illion" 
           FI
       ESAC;

   PROC base1000 rev = (LINT in n, PROC (INT,LINT)VOID yield)VOID: (
       # generates the value of the digits of n in base 1000 #
       # (i.e. 3-digit chunks), in reverse. #
       LINT n := in n;
       FOR e FROM 0 WHILE n /= 0 DO
           LINT r = n MOD 1000;
               n := n OVER 1000;
           yield(e, r)
       OD
   );

   IF n < 1000 THEN
     INT ssn := SHORTEN SHORTEN n;
     IF ssn < 0 THEN
       raise (value error, "spell integer: negative input"); ~
     ELIF ssn < 20 THEN
       small[ssn]
     ELIF ssn < 100 THEN
       INT a = ssn OVER 10,
           b = ssn MOD 10;
       tens[a] + nonzero("-", b)
     ELIF ssn < 1000 THEN
       INT a = ssn OVER 100,
           b = ssn MOD 100;
       small[a] + " hundred" + ( b NE 0 | " and" | "") + nonzero(" ", b)
     FI
   ELSE
       STRING out := "", sep:="";
     # FOR     e,      x IN # base1000 rev(n, # DO # 
          (INT e, LINT x)VOID:
               IF x NE 0 THEN
                   big(e,x) + sep +=: out;
                   sep := IF e = 0 AND x < 100 THEN " and " ELSE ", " FI
               FI
      ) 
    # OD #;
      out
   FI

);

PROC example = (LINT n)VOID:

 print((whole(n,0),": ", spell integer(n), new line));
  1. examples #

LINT prod := 0; FOR i TO 6 DO prod := prod * 10**i + i; example(prod) OD;

example(1278); example(1572); example(2010)</lang>Test output:

1: one
102: one hundred and two
102003: one hundred and two thousand and three
1020030004: one millard, twenty million, thirty thousand and four
102003000400005: one hundred and two billion, three millard, four hundred thousand and five
102003000400005000006: one hundred and two trillion, three billard, four hundred millard, five million and six
1278: one thousand, two hundred and seventy-eight
1572: one thousand, five hundred and seventy-two
2010: two thousand and ten

AutoHotkey

<lang autohotkey>Loop {  ; TEST LOOP

   n = 
   Random Digits, 1, 36               ; random number with up to 36 digits 
   Loop %Digits% { 
       Random Digit, 0, 9             ; can have leading 0s 
       n .= Digit 
   } 
   MsgBox 1, Number Names, % PrettyNumber(n) "`n`n" Spell(n) "`n`n" 
   IfMsgBox Cancel, Break 

}

Spell(n) { ; recursive function to spell out the name of a max 36 digit integer, after leading 0s removed

   Static p1=" thousand ",p2=" million ",p3=" billion ",p4=" trillion ",p5=" quadrillion ",p6=" quintillion " 
        , p7=" sextillion ",p8=" septillion ",p9=" octillion ",p10=" nonillion ",p11=" decillion " 
        , t2="twenty",t3="thirty",t4="forty",t5="fifty",t6="sixty",t7="seventy",t8="eighty",t9="ninety" 
        , o0="zero",o1="one",o2="two",o3="three",o4="four",o5="five",o6="six",o7="seven",o8="eight" 
        , o9="nine",o10="ten",o11="eleven",o12="twelve",o13="thirteen",o14="fourteen",o15="fifteen" 
        , o16="sixteen",o17="seventeen",o18="eighteen",o19="nineteen" 
   n :=RegExReplace(n,"^0+(\d)","$1") ; remove leading 0s from n 
   If  (11 < d := (StrLen(n)-1)//3)   ; #of digit groups of 3 
       Return "Number too big" 
   If (d)                             ; more than 3 digits 
       Return Spell(SubStr(n,1,-3*d)) p%d% ((s:=SubStr(n,1-3*d)) ? ", " Spell(s) : "") 
   i := SubStr(n,1,1) 
   If (n > 99)                        ; 3 digits 
       Return o%i% " hundred" ((s:=SubStr(n,2)) ? " and " Spell(s) : "") 
   If (n > 19)                        ; n = 20..99 
       Return t%i% ((o:=SubStr(n,2)) ? "-" o%o% : "") 
   Return o%n%                        ; n = 0..19 

}

PrettyNumber(n) { ; inserts thousands separators into a number string

   Return RegExReplace( RegExReplace(n,"^0+(\d)","$1"), "\G\d+?(?=(\d{3})+(?:\D|$))", "$0,")

}</lang>

BASIC

Works with: QBasic

<lang qbasic>DECLARE FUNCTION int2Text$ (number AS LONG)

'small DATA "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" DATA "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" 'tens DATA "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" 'big DATA "thousand", "million", "billion"

DIM SHARED small(1 TO 19) AS STRING, tens(7) AS STRING, big(2) AS STRING

DIM tmpInt AS INTEGER

FOR tmpInt = 1 TO 19

   READ small(tmpInt)

NEXT FOR tmpInt = 0 TO 7

   READ tens(tmpInt)

NEXT FOR tmpInt = 0 TO 2

   READ big(tmpInt)

NEXT


DIM n AS LONG

INPUT "Gimme a number! ", n PRINT int2Text$(n)

FUNCTION int2Text$ (number AS LONG)

   DIM num AS LONG, outP AS STRING, unit AS INTEGER
   DIM tmpLng1 AS LONG
   IF 0 = number THEN
       int2Text$ = "zero"
       EXIT FUNCTION
   END IF
   num = ABS(number)
   DO
       tmpLng1 = num MOD 100
       SELECT CASE tmpLng1
           CASE 1 TO 19
               outP = small(tmpLng1) + " " + outP
           CASE 20 TO 99
               SELECT CASE tmpLng1 MOD 10
                   CASE 0
                       outP = tens((tmpLng1 \ 10) - 2) + " " + outP
                   CASE ELSE
                       outP = tens((tmpLng1 \ 10) - 2) + "-" + small(tmpLng1 MOD 10) + " " + outP
               END SELECT
       END SELECT
       tmpLng1 = (num MOD 1000) \ 100
       IF tmpLng1 THEN
           outP = small(tmpLng1) + " hundred " + outP
       END IF
       num = num \ 1000
       IF num < 1 THEN EXIT DO
      
       tmpLng1 = num MOD 1000
       IF tmpLng1 THEN outP = big(unit) + " " + outP
       unit = unit + 1
   LOOP
   IF number < 0 THEN outP = "negative " + outP
   int2Text$ = RTRIM$(outP)

END FUNCTION</lang>

Sample outputs (including the answer to the ultimate question of life, the universe, and everything):

Gimme a number! 1
one
Gimme a number! 0
zero
Gimme a number! -1
negative one
Gimme a number! 42
forty-two
Gimme a number! 1000000
one million
Gimme a number! 1000000001
one billion one
Gimme a number! &h7fffffff
two billion one hundred forty-seven million four hundred eighty-three thousand six hundred forty-seven

C

Translation of: C++

This uses the code from Basic string manipulation functions. <lang c>#include <stdio.h>

  1. include "estrings.h"
  1. define setStringFromCStr(S, N) setString((S), (N), strlen(N))
  2. define appendString(S, N) do { String _t, _s; \
   _s = newString(); setStringFromCStr(_s, (N));			\
   _t = joinStrings((S),_s);						\
   copyString((S), _t); destroyString(_t); destroyString(_s); } while(0)

const char* smallNumbers[] = {

 "zero", "one", "two", "three", "four", "five",
 "six", "seven", "eight", "nine", "ten",
 "eleven", "twelve", "thirteen", "fourteen", "fifteen",
 "sixteen", "seventeen", "eighteen", "nineteen"

};

String spellHundreds(unsigned int n) {

 String res;
 res = newString();
 if (n > 99) {
   setStringFromCStr(res, smallNumbers[n/100]);
   appendString(res, " hundred");
   n %= 100;
   if (n) appendString(res, " and ");
 }
 if (n >= 20) {
   static const char* Decades[] = {
     "", "", "twenty", "thirty", "forty",
     "fifty", "sixty", "seventy", "eighty", "ninety"
   };
   appendString(res, Decades[n/10]);
   n %= 10;
   if (n) appendString(res, "-");
 }
 if (n < 20 && n > 0)
   appendString(res,smallNumbers[n]);
 return res;

}


const char* thousandPowers[] = {

 " billion", " million",  " thousand", "" };

typedef unsigned long Spellable;

String spell(Spellable n) {

 String res;
 res = newString();
 if (n < 20) return setStringFromCStr(res, smallNumbers[n]);
 const char** pScaleName = thousandPowers;
 Spellable scaleFactor = 1000000000;	// 1 billion
 while (scaleFactor > 0) {
   if (n >= scaleFactor) {
     Spellable h = n / scaleFactor;
     String t1 = spellHundreds(h);
     String t2 = joinStrings(res, t1);
     copyString(res, t2); destroyString(t2); destroyString(t1);
     appendString(res, *pScaleName);
     n %= scaleFactor;
     if (n) appendString(res, ", ");
   }
   scaleFactor /= 1000;
   ++pScaleName;
 }
 return res;

}

  1. define SPELL_IT(x) do { \
   String sp;							\
   sp = spell(x); appendChar(sp, 0);				\
   printf("%d %s\n", x, sp->bstring); destroyString(sp);	\
 } while(0)

int main() {

 SPELL_IT(      99);
 SPELL_IT(     300);
 SPELL_IT(     310);
 SPELL_IT(    1501);
 SPELL_IT(   12609);
 SPELL_IT(  512609);
 SPELL_IT(43112609);
 SPELL_IT(1234567890);
 return 0;

}</lang>

C++

<lang cpp>#include <string>

  1. include <iostream>

using std::string;

const char* smallNumbers[] = {

 "zero", "one", "two", "three", "four", "five",
 "six", "seven", "eight", "nine", "ten",
 "eleven", "twelve", "thirteen", "fourteen", "fifteen",
 "sixteen", "seventeen", "eighteen", "nineteen"

};

string spellHundreds(unsigned n) {

 string res;
 if (n > 99) {
   res = smallNumbers[n/100];
   res += " hundred";
   n %= 100;
   if (n) res += " and ";
 }
 if (n >= 20) {
   static const char* Decades[] = {
     "", "", "twenty", "thirty", "forty",
     "fifty", "sixty", "seventy", "eighty", "ninety"
   };
   res += Decades[n/10];
   n %= 10;
   if (n) res += "-";
 }
 if (n < 20 && n > 0)
   res += smallNumbers[n];
 return res;

}


const char* thousandPowers[] = {

 " billion", " million",  " thousand", "" };

typedef unsigned long Spellable;

string spell(Spellable n) {

 if (n < 20) return smallNumbers[n];
 string res;
 const char** pScaleName = thousandPowers;
 Spellable scaleFactor = 1000000000;	// 1 billion
 while (scaleFactor > 0) {
   if (n >= scaleFactor) {
     Spellable h = n / scaleFactor;
     res += spellHundreds(h) + *pScaleName;
     n %= scaleFactor;
     if (n) res += ", ";
   }
   scaleFactor /= 1000;
   ++pScaleName;
 }
 return res;

}

int main() {

  1. define SPELL_IT(x) std::cout << #x " " << spell(x) << std::endl;
 SPELL_IT(      99);
 SPELL_IT(     300);
 SPELL_IT(     310);
 SPELL_IT(    1501);
 SPELL_IT(   12609);
 SPELL_IT(  512609);
 SPELL_IT(43112609);
 SPELL_IT(1234567890);
 return 0;

}</lang> Sample output:

99 ninety-nine
300 three hundred
310 three hundred and ten
1501 one thousand, five hundred and one
12609 twelve thousand, six hundred and nine
512609 five hundred and twelve thousand, six hundred and nine
43112609 forty-three million, one hundred and twelve thousand, six hundred and nine
1234567890 one billion, two hundred and thirty-four million, five hundred and sixty-seven thousand, eight hundred and ninety

Common Lisp

<lang lisp>(format nil "~R" 1234) => "one thousand two hundred thirty-four"</lang>

D

<lang d>import std.stdio: writefln; import std.string: join;

string spell_integer(long n) {

   static string[] tens = [
       ""[], "", "twenty", "thirty", "forty",
       "fifty", "sixty", "seventy", "eighty", "ninety"];
   static string[] small = [
       "zero"[], "one", "two", "three", "four", "five",
        "six", "seven", "eight", "nine", "ten", "eleven",
        "twelve", "thirteen", "fourteen", "fifteen",
        "sixteen", "seventeen", "eighteen", "nineteen"];
   static string[] bl = [""[], "", "m", "b", "tr", "quadr",
         "quint", "sext", "sept", "oct", "non", "dec"];
   string nonzero(string c, long n) {
       return n == 0 ? "" : c ~ spell_integer(n);
   }
   string big(long e, long n) {
       if (e == 0)
           return spell_integer(n);
       else if (e == 1)
           return spell_integer(n) ~ " thousand";
       else
           return spell_integer(n) ~ " " ~ bl[e] ~ "illion";
   }
   long[] base1000_rev(long n) {
       // generates the value of the digits of n in base 1000
       // (i.e. 3-digit chunks), in reverse.
       long[] result;
       while (n != 0) {
           result ~= n % 1000;
           n /= 1000;
       }
       return result;
   }
   if (n < 0) {
       throw new Exception("spell_integer: negative input");
   } else if (n < 20) {
       return small[n];
   } else if (n < 100) {
       return tens[n / 10] ~ nonzero("-", n % 10);
   } else if (n < 1000) {
       return small[n / 100] ~ " hundred" ~ nonzero(" ", n % 100);
   } else {
       string[] pieces;
       foreach (e, x; base1000_rev(n))
           pieces ~= big(e, x);
       return pieces.reverse.join(", ");
   }

}


void main() { // example

   for (int i; i < 1000; i++)
       writefln(spell_integer(i));

}</lang>

Fortran

Works with: Fortran version 90 and later

<lang fortran>program spell

 implicit none
 integer :: e
 integer :: i
 integer :: m
 integer :: n
 character (9), dimension (19), parameter :: small =       &
   & (/'one      ', 'two      ', 'three    ', 'four     ', &
   &   'five     ', 'six      ', 'seven    ', 'eight    ', &
   &   'nine     ', 'ten      ', 'eleven   ', 'twelve   ', &
   &   'thirteen ', 'fourteen ', 'fifteen  ', 'sixteen  ', &
   &   'seventeen', 'eighteen ', 'nineteen '/)
 character (7), dimension (2 : 9), parameter :: tens =        &
   & (/'twenty ', 'thirty ', 'forty  ', 'fifty  ', 'sixty  ', &
   &   'seventy', 'eighty ', 'ninety '/)
 character (8), dimension (3), parameter :: big = &
   & (/'thousand', 'million ', 'billion '/)
 character (256) :: r
 do
   read (*, *, iostat = i) n
   if (i /= 0) then
     exit
   end if
   if (n == 0) then
     r = 'zero'
   else
     r = 
     m = abs (n)
     e = 0
     do
       if (m == 0) then
         exit
       end if
       if (modulo (m, 1000) > 0) then
         if (e > 0) then
           r = trim (big (e)) // ' ' // r
         end if
         if (modulo (m, 100) > 0) then
           if (modulo (m, 100) < 20) then
             r = trim (small (modulo (m, 100))) // ' ' // r
           else
             if (modulo (m, 10) > 0) then
               r = trim (small (modulo (m, 10))) // ' ' // r
               r = trim (tens (modulo (m, 100) / 10)) // '-' // r
             else
               r = trim (tens (modulo (m, 100) / 10)) // ' ' // r
             end if
           end if
         end if
         if (modulo (m, 1000) / 100 > 0) then
           r = 'hundred' // ' ' // r
           r = trim (small (modulo (m, 1000) / 100)) // ' ' // r
         end if
       end if
       m = m / 1000
       e = e + 1
     end do
     if (n < 0) then
       r = 'negative' // ' ' // r
     end if
   end if
   write (*, '(a)') trim (r)
 end do

end program spell</lang> Sample input: <lang>-1 0 1 42 2147483647</lang> Output: <lang>negative one zero one forty-two two billion one hundred forty-seven million four hundred eighty-three thousand six hundred forty-seven</lang>

Haskell

<lang haskell>import Data.List (intercalate, unfoldr)

spellInteger :: Integer -> String spellInteger n

| n <    0  = "negative " ++ spellInteger (-n)
| n <   20  = small n
| n <  100  = let (a, b) = n `divMod` 10
              in  tens a ++ nonzero '-' b
| n < 1000  = let (a, b) = n `divMod` 100
              in  small a ++ " hundred" ++ nonzero ' ' b
| otherwise = intercalate ", " $ map big $ reverse $
              filter ((/= 0) . snd) $ zip [0..] $ unfoldr uff n
where nonzero :: Char -> Integer -> String
      nonzero _ 0 = ""
      nonzero c n = c : spellInteger n
      uff :: Integer -> Maybe (Integer, Integer)
      uff 0 = Nothing
      uff n = Just $ uncurry (flip (,)) $ n `divMod` 1000
      small, tens :: Integer -> String
      small = (["zero", "one", "two", "three", "four", "five",
           "six", "seven", "eight", "nine", "ten", "eleven",
           "twelve", "thirteen", "fourteen", "fifteen", "sixteen",
           "seventeen", "eighteen", "nineteen"] !!) . fromEnum
      tens = ([undefined, undefined, "twenty", "thirty", "forty",
          "fifty", "sixty", "seventy", "eighty", "ninety"] !!) .
          fromEnum
      big :: (Int, Integer) -> String
      big (0, n) = spellInteger n
      big (1, n) = spellInteger n ++ " thousand"
      big (e, n) = spellInteger n ++ ' ' : (l !! e) ++ "illion"
        where l = [undefined, undefined, "m", "b", "tr", "quadr",
                  "quint", "sext", "sept", "oct", "non", "dec"]</lang>

HicEst

<lang HicEst>SUBROUTINE NumberToWords(number)

CHARACTER outP*255, small*130, tens*80, big*80
REAL ::   decimal_places = 7
INIT( APPENDIX("#literals"), small, tens, big)
num = ABS( INT(number) )
order = 0
outP = ' '
DO i = 1, num + 1
  tmp = MOD(num, 100)
  IF(tmp > 19) THEN
      EDIT(Text=tens, ITeM=INT(MOD(tmp/10, 10)), Parse=medium)
      IF( MOD(tmp, 10) ) THEN
          EDIT(Text=small, ITeM=MOD(tmp,10)+1, Parse=mini)
          outP = medium // '-' // mini // ' ' // outP
      ELSE
          outP = medium // ' ' // outP
      ENDIF
  ELSEIF(tmp > 0) THEN
      EDIT(Text=small, ITeM=tmp+1, Parse=mini)
      outP = mini // ' '// outP
  ELSEIF(number == 0) THEN
      outP = 'zero'
  ENDIF
  tmp = INT(MOD(num, 1000) / 100)
  IF(tmp) THEN
      EDIT(Text=small, ITeM=tmp+1, Parse=oneto19)
      outP = oneto19 // ' hundred ' // outP
  ENDIF
  num = INT(num /1000)
  IF( num == 0) THEN
      IF(number < 0) outP = 'minus ' // outP
      fraction = ABS( MOD(number, 1) )
      IF(fraction) WRITE(Text=outP, APPend) ' point'
      DO j = 1, decimal_places
        IF( fraction >= 10^(-decimal_places) ) THEN
            num = INT( 10.01 * fraction )
            EDIT(Text=small, ITeM=num+1, Parse=digit)
            WRITE(Text=outP, APPend) ' ', digit
            fraction = 10*fraction - num
        ENDIF
      ENDDO
      OPEN(FIle="temp.txt", APPend)
      WRITE(FIle="temp.txt", Format='F10, " = ", A', CLoSe=1) number, outP
      RETURN
  ENDIF
  order = order + 1
  EDIT(Text=big, ITeM=order, Parse=kilo)
  IF( MOD(num, 1000) ) outP = kilo // ' and '// outP
ENDDO

END

CALL NumberToWords( 0 ) CALL NumberToWords( 1234 ) CALL NumberToWords( 1234/100 ) CALL NumberToWords( 10000000 + 1.2 ) CALL NumberToWords( 2^15 ) CALL NumberToWords( 0.001 ) CALL NumberToWords( -EXP(1) )

  1. literals
SMALL= zero one two three four five six seven eight nine ten &
eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen
TENS=ten twenty thirty forty fifty sixty seventy eighty ninety
BIG=thousand million billion trillion quadrillion</lang>

<lang HicEst>0 = zero 1234 = one thousand and two hundred thirty-four 12.34 = twelve point three four 10000001.2 = ten million and one point two 32768 = thirty-two thousand and seven hundred sixty-eight 1E-3 = point zero zero one -2.7182818 = minus two point seven one eight two eight one eight</lang>

Icon and Unicon

Icon

<lang Icon>link numbers # commas, spell

procedure main(arglist) every x := !arglist do

  write(commas(x), " -> ",spell(x))

end</lang>

numbers:spell was used as a based for this procedure.

<lang Icon>procedure spell(n) #: spell out integer (short scale)

  local m, i
  static scale 
  initial {
     scale := [ "thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion","septillion"]  
     every scale[i := 1 to *scale ] := [ integer(repl("999",i + 1)), -3 * i, " "||scale[i] ]
     push(scale,[999,2," hundred"])
    }
  n := integer(n) | stop(image(n)," is not an integer")
  if n < 0 then return "negative " || spell(-n)
  if n <= 12 then return {
     "0zero,1one,2two,3three,4four,5five,6six,7seven,8eight,_
        9nine,10ten,11eleven,12twelve," ? {
           tab(find(n))
           move(*n)
           tab(find(","))
           }
     }
  else if n <= 19 then return {
     spell(n[2] || "0") ?
        (if ="for" then "four" else tab(find("ty"))) || "teen"
     }
  else if n <= 99 then return {
     "2twen,3thir,4for,5fif,6six,7seven,8eigh,9nine," ? {
        tab(find(n[1]))
        move(1)
        tab(find(",")) || "ty" ||
           (if n[2] ~= 0 then "-" || spell(n[2]) else "")
        }
     }
  else if n <= scale[i := 1 to *scale,1] then return {     # generalize based on scale
     spell(n[1:scale[i,2]]) || scale[i,3] ||
        (if (m := n[scale[i,2]:0]) ~= 0 then " and " || spell(m) else "")   
     }
  else fail                                                # really big

end</lang> Sample output:

#spell.exe 5 11 15 67 10132767 65535 -1234567890123456

5 -> five
11 -> eleven
15 -> fifteen
67 -> sixty-seven
10,132,767 -> ten million and one hundred and thirty-two thousand and seven hundred and sixty-seven
65,535 -> sixty-five thousand and five hundred and thirty-five
-1,234,567,890,123,456 -> negative one quadrillion and two hundred and thirty-four trillion and five hundred and sixty-seven billion and eight hundred and ninety million and one hundred and twenty-three thousand and four hundred and fifty-six

Unicon

This Icon solution works in Unicon.

Inform 7

Works with: Z-machine

<lang inform7>say 32767 in words;</lang>

<lang inform7>say 2147483647 in words;</lang>

J

Solutions: <lang j>u=. ;:'one two three four five six seven eight nine' v=. ;:'ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen' t=. ;:'twenty thirty forty fifty sixty seventy eighty ninety' EN100=:  ; u , v , , t ,&.>/ ;'-',&.>u

z=.  ; 'thousand' ; (;:'m b tr quadr quint sext sept oct non'),&.> <'illion' u=. ;:'un duo tre quattuor quin sex septen octo novem' t=. (;:'dec vigint trigint quadragint quinquagint sexagint septuagint octogint nonagint'),&.><'illion' ENU=: z , (, t ,~&.>/ ;u) , <'centillion'

en3=: 4 : 0

'p q'=. 0 100#:y
(p{::EN100),((*p)#' hundred'),((p*&*q)#x),q{::EN100

)

en=: 4 : 0

d=. 1000&#.^:_1 y
assert. (0<:y) *. ((=<.)y) *. d <:&# ENU
c=. x&en3&.> (*d)#d
((0=y)#'zero') , (-2+*{:d) }. ; , c,.(<' '),.(ENU{~I.&.|.*d),.<', '

)

uk=: ' and '&en NB. British us=: ' ' &en NB. American</lang>

Example: <lang> uk 123456789 one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine

  us 123456789

one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine

  us 1234567890123456789012345678901234567890123456789012345678901234567890x

one duovigintillion, two hundred thirty-four unvigintillion, five hundred sixty-seven vigintillion, eight hundred ninety novemdecillion, one hundred twenty-three octodecillion, four hundred fifty-six septendecillion, seven hundred eighty-nine sexdecillion, twelve quindecillion, three hundred forty-five quattuordecillion, six hundred seventy-eight tredecillion, nine hundred one duodecillion, two hundred thirty-four undecillion, five hundred sixty-seven decillion, eight hundred ninety nonillion, one hundred twenty-three octillion, four hundred fifty-six septillion, seven hundred eighty-nine sextillion, twelve quintillion, three hundred forty-five quadrillion, six hundred seventy-eight trillion, nine hundred one billion, two hundred thirty-four million, five hundred sixty-seven thousand, eight hundred ninety</lang>

Java

Translation of: BASIC

<lang java>public class Int2Words {

   static String[] small = {"one", "two", "three", "four", "five", "six",
       "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
       "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
   static String[] tens = {"twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty",
       "ninety"};
   static String[] big = {"thousand", "million", "billion", "trillion"};
   public static void main(String[] args) {
       System.out.println(int2Text(900000001));
       System.out.println(int2Text(1234567890));
       System.out.println(int2Text(-987654321));
       System.out.println(int2Text(0));
   }
   public static String int2Text(long number) {
       long num = 0;
       String outP = "";
       int unit = 0;
       long tmpLng1 = 0;
       if (number == 0) {
           return "zero";
       }
       num = Math.abs(number);
       for (;;) {
           tmpLng1 = num % 100;
           if (tmpLng1 >= 1 && tmpLng1 <= 19) {
               outP = small[(int) tmpLng1 - 1] + " " + outP;
           } else if (tmpLng1 >= 20 && tmpLng1 <= 99) {
               if (tmpLng1 % 10 == 0) {
                   outP = tens[(int) (tmpLng1 / 10) - 2] + " " + outP;
               } else {
                   outP = tens[(int) (tmpLng1 / 10) - 2] + "-"
                           + small[(int) (tmpLng1 % 10) - 1] + " " + outP;
               }
           }
           tmpLng1 = (num % 1000) / 100;
           if (tmpLng1 != 0) {
               outP = small[(int) tmpLng1 - 1] + " hundred " + outP;
           }
           num /= 1000;
           if (num == 0) {
               break;
           }
           tmpLng1 = num % 1000;
           if (tmpLng1 != 0) {
               outP = big[unit] + " " + outP;
           }
           unit++;
       }
       if (number < 0) {
           outP = "negative " + outP;
       }
       return outP.trim();
   }

}</lang> Output:

nine hundred million one
one billion two hundred thirty-four million five hundred sixty-seven thousand eight hundred ninety
negative nine hundred eighty-seven million six hundred fifty-four thousand three hundred twenty-one
zero

<lang logo> make "numbers {one two three four five six seven eight nine ten

    eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen}

make "tens {twenty thirty forty fifty sixty seventy eighty ninety}@2

make "thou [[] thousand million billion trillion] ; expand as desired

to to.english.thou :n :thou

 if :n = 0    [output []]
 if :n < 20   [output sentence item :n :numbers  first :thou]
 if :n < 100  [output (sentence item int :n/10 :tens
                                to.english.thou modulo :n 10 [[]]
                                first :thou)]
 if :n < 1000 [output (sentence item int :n/100 :numbers
                                "hundred
                                to.english.thou modulo :n 100 [[]]
                                first :thou)]
 output (sentence to.english.thou int :n/1000 butfirst :thou
                  to.english.thou modulo :n 1000 :thou)

end

to to.english :n

 if :n = 0 [output "zero]
 if :n > 0 [output to.english.thou :n :thou]
 [output sentence "negative to.english.thou minus :n :thou]

end

print to.english 1234567  ; one million two hundred thirty four thousand five hundred sixty seven </lang>

Lua

<lang lua> words = {"one ", "two ", "three ", "four ", "five ", "six ", "seven ", "eight ", "nine "} levels = {"thousand ", "million ", "billion ", "trillion ", "quadrillion ", "quintillion ", "sextillion ", "septillion ", "octillion ", [0] = ""} iwords = {"ten ", "twenty ", "thirty ", "forty ", "fifty ", "sixty ", "seventy ", "eighty ", "ninety "} twords = {"eleven ", "twelve ", "thirteen ", "fourteen ", "fifteen ", "sixteen ", "seventeen ", "eighteen ", "nineteen "}

function digits(n)

 local i, ret = -1
 return function()
   i, ret = i + 1, n % 10

if n > 0 then

     n = math.floor(n / 10)

return i, ret end

 end

end

level = false function getname(pos, dig) --stateful, but effective.

 level = level or pos % 3 == 0
 if(dig == 0) then return "" end
 local name = (pos % 3 == 1 and iwords[dig] or words[dig]) .. (pos % 3 == 2 and "hundred " or "")
 if(level) then name, level = name .. levels[math.floor(pos / 3)], false end
 return name

end

local val, vword = io.read() + 0, ""

for i, v in digits(val) do

 vword = getname(i, v) .. vword

end

for i, v in ipairs(words) do

 vword = vword:gsub("ty " .. v, "ty-" .. v)
 vword = vword:gsub("ten " .. v, twords[i])

end

if #vword == 0 then print "zero" else print(vword) end </lang>

MAXScript

This example isn't a very succinct way to solve the problem, but the way it works should be quite obvious. The function will work for values up to 1000 <lang MAXScript>fn NumberToWord myNum = ( local Result = "" while myNum != 0 do ( Result += case of ( (myNum >= 1000):(myNum -= 1000; "one thousand") (myNum > 900): (myNum -= 900 ; "nine hundred and") (myNum == 900): (myNum -= 900 ; "nine hundred") (myNum > 800): (myNum -= 800 ; "eight hundred and") (myNum == 800): (myNum -= 900 ; "eight hundred") (myNum > 700): (myNum -= 700 ; "seven hundred and") (myNum == 700): (myNum -= 900 ; "seven hundred") (myNum > 600): (myNum -= 600 ; "six hundred and") (myNum == 600): (myNum -= 900 ; "six hundred") (myNum > 500): (myNum -= 500 ; "five hundred and") (myNum == 500): (myNum -= 900 ; "five hundred") (myNum > 400): (myNum -= 400 ; "four hundred and") (myNum == 400): (myNum -= 900 ; "four hundred") (myNum > 300): (myNum -= 300 ; "three hundred and") (myNum == 300): (myNum -= 900 ; "three hundred") (myNum > 200): (myNum -= 200 ; "two hundred and") (myNum == 200): (myNum -= 900 ; "two hundred") (myNum > 100): (myNum -= 100 ; "one hundred and") (myNum == 100): (myNum -= 100 ; "one hundred") (myNum >= 90): (myNum -= 90  ; "ninety") (myNum >= 80): (myNum -= 80  ; "eighty") (myNum >= 70): (myNum -= 70  ; "seventy") (myNum >= 60): (myNum -= 60  ; "sixty") (myNum >= 50): (myNum -= 50  ; "fifty") (myNum >= 40): (myNum -= 40  ; "fourty") (myNum >= 30): (myNum -= 30  ; "thirty") (myNum >= 20): (myNum -= 20  ; "twenty") (myNum >= 19): (myNum -= 19  ; "nineteen") (myNum >= 18): (myNum -= 18  ; "eighteen") (myNum >= 17): (myNum -= 17  ; "seventeen") (myNum >= 16): (myNum -= 16  ; "sixteen") (myNum >= 15): (myNum -= 15  ; "fifteen") (myNum >= 14): (myNum -= 14  ; "fourteen") (myNum >= 13): (myNum -= 13  ; "thirteen") (myNum >= 12): (myNum -= 12  ; "twelve") (myNum >= 11): (myNum -= 11  ; "eleven") (myNum >= 10): (myNum -= 10  ; "ten") (myNum >= 9): (myNum -= 9  ; "nine") (myNum >= 8): (myNum -= 8  ; "eight") (myNum >= 7): (myNum -= 7  ; "seven") (myNum >= 6): (myNum -= 6  ; "six") (myNum >= 5): (myNum -= 5  ; "five") (myNum >= 4): (myNum -= 4  ; "four") (myNum >= 3): (myNum -= 3  ; "three") (myNum >= 2): (myNum -= 2  ; "two") (myNum >= 1): (myNum -= 1  ; "one") ) if myNum != 0 then result += " " ) result )</lang>

Example: <lang MAXScript>NumberToWord(123)</lang>

OCaml

<lang ocaml>let div_mod n d = (n / d, n mod d) let join = String.concat ", " ;;

let rec nonzero = function

 | _, 0 -> ""
 | c, n -> c ^ (spell_integer n)

and tens n =

 [| ""; ""; "twenty"; "thirty"; "forty"; "fifty";
            "sixty"; "seventy"; "eighty"; "ninety" |].(n)

and small n =

 [| "zero"; "one"; "two"; "three"; "four"; "five";
    "six"; "seven"; "eight"; "nine"; "ten"; "eleven";
    "twelve"; "thirteen"; "fourteen"; "fifteen";
    "sixteen";"seventeen"; "eighteen"; "nineteen" |].(n)

and bl = [| ""; ""; "m"; "b"; "tr"; "quadr"; "quint";

                   "sext"; "sept"; "oct"; "non"; "dec" |]

and big = function

 | 0, n -> (spell_integer n)
 | 1, n -> (spell_integer n) ^ " thousand"
 | e, n -> (spell_integer n) ^ " " ^ bl.(e) ^ "illion"

and uff acc = function

 | 0 -> List.rev acc
 | n ->
     let a, b = div_mod n 1000 in
     uff (b::acc) a

and spell_integer = function

 | n when n < 0 -> invalid_arg "spell_integer: negative input"
 | n when n < 20 -> small n
 | n when n < 100 ->
     let a, b = div_mod n 10 in
     (tens a) ^ nonzero("-", b)
 | n when n < 1000 ->
     let a, b = div_mod n 100 in
     (small a) ^ " hundred" ^ nonzero(" ", b)
 | n ->
     let seg = (uff [] n) in
     let _, segn =
       (* just add the index of the item in the list *)
       List.fold_left
         (fun (i,acc) v -> (succ i, (i,v)::acc))
         (0,[])
         seg
     in
     let fsegn =
       (* remove right part "zero" *)
       List.filter
         (function (_,0) -> false | _ -> true)
         segn
     in
     join(List.map big fsegn)
</lang>

PARI/GP

<lang>Eng(n:int)={ my(tmp,s=""); if (n >= 1000000, tmp = n\1000000; s = Str(Eng(tmp), " million"); n -= tmp * 1000000; if (!n, return(s)); s = Str(s, " ") ); if (n >= 1000, tmp = n\1000; s = Str(Eng(tmp), " thousand"); n -= tmp * 1000; if (!n, return(s)); s = Str(s, " ") ); if (n >= 100, tmp = n\100; s = Str(Edigit(tmp), " hundred"); n -= tmp * 100; if (!n, return(s)); s = Str(s, " ") ); if (n < 20, return (Str(s, ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "ninteen"][n])) ); tmp = n\10; s = Str(s, [0, "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"][tmp]); n -= tmp * 10; if (n, Str(s, "-", Edigit(n)), s) }; Edigit(n)={ ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine"][n] };</lang>

Perl

<lang perl>use Lingua::EN::Numbers 'num2en';

print num2en(123456789), "\n";</lang>

PHP

<lang php>$orderOfMag = array("Hundred", "Thousand,", "Million,", "Billion,", "Trillion,"); $smallNumbers = array("Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"); $decades = array("", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety");

function NumberToEnglish($num, $count = 0){

  global $orderOfMag, $smallNumbers, $decades;
  $isLast = true;
  $str = "";
  if ($num < 0){
     $str = "Negative ";
     $num = abs($num);
  }
  (int) $thisPart = substr((string) $num, -3);
  if (strlen((string) $num) > 3){
     // Number still too big, work on a smaller chunk
     $str .= NumberToEnglish((int) substr((string) $num, 0, strlen((string) $num) - 3), $count + 1);
     $isLast = false;
  }
  // do translation stuff
  if (($count == 0 || $isLast) && ($str == "" || $str == "Negative "))
     // This is either a very small number or the most significant digits of the number. Either way we don't want a preceeding "and"
     $and = "";
  else
     $and = " and ";
  if ($thisPart > 99){
     // Hundreds part of the number chunk
     $str .= ($isLast ? "" : " ") . "{$smallNumbers[$thisPart/100]} {$orderOfMag[0]}";
     if(($thisPart %= 100) == 0){
        // There is nothing else to do for this chunk (was a multiple of 100)
        $str .= " {$orderOfMag[$count]}";
        return $str;
     }
     $and = " and ";  // Set up our and string to the word "and" since there is something in the hundreds place of this chunk
  }
  if ($thisPart >= 20){
     // Tens part of the number chunk
     $str .= "{$and}{$decades[$thisPart /10]}";
     $and = " "; // Make sure we don't have any extranious "and"s
     if(($thisPart %= 10) == 0)
        return $str . ($count != 0 ? " {$orderOfMag[$count]}" : "");
  }
  if ($thisPart < 20 && $thisPart > 0)
     // Ones part of the number chunk
     return $str . "{$and}{$smallNumbers[(int) $thisPart]} " . ($count != 0 ? $orderOfMag[$count] : "");
  elseif ($thisPart == 0 && strlen($thisPart) == 1)
     // The number is zero
     return $str . "{$smallNumbers[(int)$thisPart]}";

}</lang> Example: <lang>NumberToEnglish(0); NumberToEnglish(12); NumberToEnglish(123); NumberToEnglish(1234567890123); NumberToEnglish(65535); NumberToEnglish(-54321);</lang> Returns: <lang>Zero Twelve One Hundred and Twenty Three One Trillion, Two Hundred and Thirty Four Billion, Five Hundred and Sixty Seven Million, Eight Hundred and Ninety Thousand, One Hundred and Twenty Three Sixty Five Thousand, Five Hundred and Thirty Five Negative Fifty Four Thousand, Three Hundred and Twenty One</lang>

PicoLisp

<lang PicoLisp>(de numName (N)

  (cond
     ((=0 N) "zero")
     ((lt0 N) (pack "minus " (numName (- N))))
     (T (numNm N)) ) )

(de numNm (N)

  (cond
     ((=0 N))
     ((> 14 N)
        (get '("one" "two" "three" "four" "five" "six" "seven" "eight" "nine" "ten" "eleven" "twelve" "thirteen") N) )
     ((= 15 N) "fifteen")
     ((= 18 N) "eighteen")
     ((> 20 N) (pack (numNm (% N 10)) "teen"))
     ((> 100 N)
        (pack
           (get '("twen" "thir" "for" "fif" "six" "seven" "eigh" "nine") (dec (/ N 10)))
           "ty"
           (unless (=0 (% N 10))
              (pack "-" (numNm (% N 10))) ) ) )
     ((rank N '((100 . "hundred") (1000 . "thousand") (1000000 . "million")))
        (pack (numNm (/ N (car @))) " " (cdr @) " " (numNm (% N (car @)))) ) ) )</lang>

PL/I

<lang PL/I>

  declare integer_names (0:20) character (9) varying static initial
     ('zero',  'one',   'two',  'three', 'four',   'five', 'six',
      'seven', 'eight', 'nine', 'ten',   'eleven', 'twelve',
      'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen',
      'eighteen', 'nineteen', 'twenty' );
  declare x(10) character (7) varying static initial
     ('ten', 'twenty', 'thirty', 'fourty', 'fifty',
      'sixty', 'seventy', 'eighty', 'ninety', 'hundred');
  declare y(0:5) character (10) varying static initial
     (, , ' thousand ', ' million ', ' billion ', ' trillion ');
  declare (i, j, m, t) fixed binary (31);
  declare (units, tens, hundreds, thousands) fixed binary (7);
  declare (h, v, value) character (200) varying;
  declare (d, k, n) fixed decimal (15);
  declare three_digits fixed decimal (3);
     value = ;
     i = 5;
     k = n;
     do d = 1000000000000 repeat d/1000 while (d > 0);
        i = i - 1;
        three_digits = k/d;
        k = mod(k, d);
        if three_digits = 0 then iterate;
        units = mod(three_digits, 10);
        t = three_digits / 10;
        tens = mod(t, 10);
        hundreds = three_digits / 100;
        m = mod(three_digits, 100);
        if m <= 20 then
           v = integer_names(m);
        else if units = 0 then
           v = ;
        else
           v = integer_names(units);
        if tens >= 2 & units ^= 0 then
           v = x(tens) || v;
        else if tens > 2 & units = 0 then
           v = v || x(tens);
        if units + tens = 0 then
           if n > 0 then  v = ;
        if hundreds > 0 then
           h = integer_names(hundreds) || ' hundred ';
        else
           h = ;
        if three_digits > 100 & (tens + units > 0) then
           v = 'and ' || v;
        if i = 1 & value ^=  & three_digits <= 9 then
           v = 'and ' || v;
        value = value ||h || v || y(i);
     end;
     put skip edit (trim(N), ' = ', value) (a);

</lang>

PowerBASIC

Translation of: BASIC

Note that the PB compiler seems to have some bugs related to the QUAD data type; see the sample output below the code.

<lang powerbasic>FUNCTION int2Text (number AS QUAD) AS STRING

   IF 0 = number THEN
       FUNCTION = "zero"
       EXIT FUNCTION
   END IF
   DIM num AS QUAD, outP AS STRING, unit AS LONG
   DIM tmpLng1 AS QUAD
   DIM small(1 TO 19) AS STRING, tens(7) AS STRING, big(5) AS STRING
   DIM tmpInt AS LONG, dcnt AS LONG
   ARRAY ASSIGN small() = "one", "two", "three", "four", "five", "six", _
                          "seven", "eight", "nine", "ten", "eleven", _
                          "twelve", "thirteen", "fourteen", "fifteen", _
                          "sixteen", "seventeen", "eighteen", "nineteen"
   ARRAY ASSIGN tens() = "twenty", "thirty", "forty", "fifty", "sixty", _
                         "seventy", "eighty", "ninety"
   ARRAY ASSIGN big() = "thousand", "million", "billion", "trillion", _
                        "quadrillion", "quintillion"
   num = ABS(number)
   DO
       tmpLng1 = num MOD 100
       SELECT CASE tmpLng1
           CASE 1 TO 19
               outP = small(tmpLng1) + " " + outP
           CASE 20 TO 99
               SELECT CASE tmpLng1 MOD 10
                   CASE 0
                       outP = tens((tmpLng1 \ 10) - 2) + " " + outP
                   CASE ELSE
                       outP = tens((tmpLng1 \ 10) - 2) + "-" + small(tmpLng1 MOD 10) + " " + outP
               END SELECT
       END SELECT
       tmpLng1 = (num MOD 1000) \ 100
       IF tmpLng1 THEN
           outP = small(tmpLng1) + " hundred " + outP
       END IF
       num = num \ 1000
       IF num < 1 THEN EXIT DO
       tmpLng1 = num MOD 1000
       IF tmpLng1 THEN outP = big(unit) + " " + outP
       unit = unit + 1
   LOOP
   IF number < 0 THEN outP = "negative " + outP
   FUNCTION = RTRIM$(outP)

END FUNCTION


FUNCTION PBMAIN () AS LONG

   DIM n AS QUAD
   #IF %DEF(%PB_CC32)
       INPUT "Gimme a number! ", n
   #ELSE
       n = VAL(INPUTBOX$("Gimme a number!", "Now!"))
   #ENDIF
   ? int2Text(n)

END FUNCTION</lang>

Sample output:

Gimme a number! 1111111111111111111
one quintillion one hundred eleven quadrillion one hundred eleven trillion one h
undred eleven billion one hundred eleven million one hundred eleven thousand one
hundred ten

PureBasic

The range of integers handled has been set at an obscene 45 digits. <lang PureBasic>DataSection

 numberNames:
 ;small
 Data.s "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"
 Data.s "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
 ;tens
 Data.s "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"
 ;big, non-Chuquet system 
 Data.s "thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion"
 Data.s "septillion", "octillion", "nonillion", "decillion", "undecillion", "duodecillion"
 Data.s "tredecillion"

EndDataSection

Procedure.s numberWords(number.s)

 ;handles integers from -1E45 to +1E45
 Static isInitialized = #False
 Static Dim small.s(19)
 Static Dim tens.s(9)
 Static Dim big.s(14)
 
 If Not isInitialized
   Restore numberNames
   For i = 1 To 19
     Read.s small(i)
   Next
   For i = 2 To 9
     Read.s tens(i)
   Next
   For i = 1 To 14
     Read.s big(i)
   Next
   isInitialized = #True
 EndIf 
 
 For i = 1 To Len(number)
   If Not FindString("- 0123456789", Mid(number,i,1), 1)
     number = Left(number, i - 1) ;trim number to the last valid character
     Break ;exit loop
   EndIf 
 Next 
 
 Protected IsNegative = #False
 number = Trim(number)
 If Left(number,1) = "-"
   IsNegative = #True
   number = Trim(Mid(number, 2))
 EndIf 
 
 If CountString(number, "0") = Len(number)
   ProcedureReturn "zero"
 EndIf 
 
 If Len(number) > 45
   ProcedureReturn "Number is too big!"
 EndIf 
 
 Protected num.s = number, output.s, unit, unitOutput.s, working
 
 Repeat
   working = Val(Right(num, 2))
   unitOutput = ""
   Select working
     Case 1 To 19
       unitOutput = small(working)
     Case 20 To 99
       If working % 10
         unitOutput = tens(working / 10) + "-" + small(working % 10)
       Else
         unitOutput = tens(working / 10)
       EndIf 
   EndSelect
   
   working = Val(Right(num, 3)) / 100
   If working
     If unitOutput <> ""
       unitOutput = small(working) + " hundred " + unitOutput
     Else
       unitOutput = small(working) + " hundred"
     EndIf 
   EndIf 
   
   If unitOutput <> "" And unit > 0
     unitOutput + " " + big(unit)
     If output <> ""
       unitOutput + ", "
     EndIf 
   EndIf 
   
   output = unitOutput + output
   
   If Len(num) > 3
     num = Left(num, Len(num) - 3)
     unit + 1
   Else
     Break ;exit loop
   EndIf 
 ForEver
 
 If IsNegative
   output = "negative " + output
 EndIf
 
 ProcedureReturn output

EndProcedure

Define n$ If OpenConsole()

 Repeat
   Repeat
     Print("Give me an integer (or q to quit)! ")
     n$ = Input()
   Until n$ <> ""
   
   If Left(Trim(n$),1) = "q"
     Break ;exit loop
   EndIf 
   PrintN(numberWords(n$))
 ForEver 
 CloseConsole()

EndIf </lang> Sample output:

Give me an integer (or q to quit)! 3
three
Give me an integer (or q to quit)! -1327
negative one thousand, three hundred twenty-seven
Give me an integer (or q to quit)! 0
zero
Give me an integer (or q to quit)! 100000000002000000000000000300000000000000004
one hundred tredecillion, two decillion, three hundred quadrillion, four

Python

<lang python>def spell_integer(n):

   tens = [None, None, "twenty", "thirty", "forty",
           "fifty", "sixty", "seventy", "eighty", "ninety"]
   small = ["zero", "one", "two", "three", "four", "five",
            "six", "seven", "eight", "nine", "ten", "eleven",
            "twelve", "thirteen", "fourteen", "fifteen",
            "sixteen", "seventeen", "eighteen", "nineteen"]
   bl = [None, None, "m", "b", "tr", "quadr",
         "quint", "sext", "sept", "oct", "non", "dec"]
   def nonzero(c, n):
       return "" if n == 0 else c + spell_integer(n)
   def big(e, n):
       if e == 0:
           return spell_integer(n)
       elif e == 1:
           return spell_integer(n) + " thousand"
       else:
           return spell_integer(n) + " " + bl[e] + "illion"
   def base1000_rev(n):
       # generates the value of the digits of n in base 1000
       # (i.e. 3-digit chunks), in reverse.
       while n != 0:
           n, r = divmod(n, 1000)
           yield r
   if n < 0:
       raise ValueError, "spell_integer: negative input"
   elif n < 20:
       return small[n]
   elif n < 100:
       a, b = divmod(n, 10)
       return tens[a] + nonzero("-", b)
   elif n < 1000:
       a, b = divmod(n, 100)
       return small[a] + " hundred" + nonzero(" ", b)
   else:
       return ", ".join([big(e, x) for e, x in
                         enumerate(base1000_rev(n)) if x][::-1])
  1. example

print spell_integer(1278) print spell_integer(1752) print spell_integer(2010) </lang>

one thousand, two hundred seventy-eight
one thousand, seven hundred fifty-two
two thousand, ten

REXX

As I understand the task's parameters, it was OK to used a pre-existing program to solve this
task.  I had first considered taking the original program and ripping out all the good stuff
and just solve the primary task (and optional requirements), but it was taking too much time
so I left the program intact, negated the use of the  $T  program (which essentially is a TYPE
command that can show text in colors, does vertical and horizontal [indentation] tabbing,
boxing, centering/justification, and writing the output to a file, waits on confirmation,
block letters, splitting of message text [multiple lines], highlighting of text portions
[in colors], among other things).

Also not included is the  $H  program which shows (among other things) the help
(documentation), and the  $ERR  program which issues error messages (in red).  I assume that
most people could figure out what the error message(s) would be by observing the context.

This REXX program supports: 

  * long & short scale (American and English styles)
  * ordinal numbers and cardinal numbers
  * expressing the number as a YEAR  (1975 would be nineteen seventy-five)
  * decimal points  (6 is different than 6.)
  * decimal fractions
  * numbers with leading zeroes (as well as trailing zeroes)
  * leading signs (+ or -)
  * exponential notation
  * currency symbols
  * adding commas (or whatever) to the output (including blanks)
  * numbers (American) up to 3,000 digits, (English) up to 6,000 digits
  * numbers with suffixes such as K, M, Gi, etc, and also some common ones as well as factorials
  * user-defineable names for: signs, decimal point, power, curreny symbols, zero (digit), etc.

The program has a pretty hefty prologue which determines (among other things):

  * the operating system (and maybe the type)
  * the name of the REXX program: it's filename, filetype, filemode (or path, if you will)
  * the access-name to acquire environmental variables
  * if EBCDIC or ASCII system
  * which REXX (or KEXX) is being used
  * the name of the program (command) to clear the terminal screen
  * if appropriate, invokes $H to show the help/logic flow/sample uses/or program author



If there are strong feelings that the code should be removed because of it's length, I'll remove it.


I'm still working on the program to reduce the amount of names by programatically generating any 
number of names (instead of having a fixed amount of names in text form).

REXX program

/**/trace o;parse arg !;if !all(arg()) then exit;if !cms then address '';signal on halt;signal on novalue;signal on syntax
@abc='abcdefghijklmnopqrstuvwxyz'
american=0
andcent='and'
asayear=0
asis=0
blanks=
british=0
cent='cent'
clear=0
colors=!cms | !pcrexx | !r4 | !roo
dollar='dollar'
dot=
english=0
euro='euro'
exponents=
fractions=
franc='franc'
leading=
leadingz=
logs=0
minus='minus '
n=
nothing='zero'
ops=space(!!)
ordinal=0
piseta='piseta'
plus='plus '
point='point'
pound='pound'
power='power'
quiet=0
raised='times ten raised to the'
sep='none'
single=0
tfid=                                            /*temporary file id.   */
tops=
xcurr=
yen='yen'
zero='oh'

  do while ops\==''                   /*process user arguments & options*/
  parse var ops _1 2 1 _ . 1 _o ops
  upper _
    select
    when isnum(_)                 then n=n||_
    when _==',' | _=="(" | _==')' then nop
    when _1=='.' & pos("=",_)\==0 then tops=tops _o
    when abbn('AMERican')         then american=no()
    when abbn('ASAYEAR')|,
         abbn('ASYEAR')|,
         abbn('YEAR')             then asayear=no()
    when  abb('BEINGRAISed')|,
          abb('RAISEd')           then raised=na()
    when  abb('BLANKs')           then blanks=na()
    when abbn('BRITish')          then british=no()
    when  abb('CENTs')            then cent=na()
    when abbn('CLearscreen')      then clear=no()
    when abbn('COLORs')           then colors=no()
    when  abb('DECIMALpoints')|,
          abb('DOLLARs')          then dollar=na()
    when abbn('ENGlish')          then english=no()
    when  abb('EUROs')            then euro=na()
    when  abb('FRANCs')           then franc=na()
    when  abb('LEADINGzeroes')|,
          abb('LEADINGzeros')     then leading=na()
    when abbn('LOGs')             then logs=no()
    when  abb('MINUSsigns')|,
          abb('MINUSes')          then minus=na()' '
    when  abb('NOTHINGs')         then nothing=na()
    when abbn('ORDinal')          then ordinal=no()
    when  abb('PISETAs')          then piseta=na()
    when  abb('POWer')            then power=na()
    when  abb('PLUSsigns')|,
          abb('PLUSes')           then plus=na()' '
    when  abb('POINTs')           then point=na()
    when  abb('POUNDs')           then pound=na()
    when abbn('Quiet')            then quiet=no()
    when  abb('SEPerators')       then sep=na()
    when abbn('SINGley')          then single=no()
    when  abb('YENs')             then yen=na()
    when  abb('ZEROs')|,
          abb('ZEROes')           then zero=na()
    otherwise n=n||_o
    end
  end

if sep=='none' then if pos(',',n)\==0 then sep=','
if sep=='none' then sep=
ogn=n                                /* original number that was entered*/
_=blanks                             /* validate BLANKS= option.*/
l=length(_)
if l>3 then call er 55,_

if l==3 then do                      /* decimal value.*/
             if \isint(_) then call er 92,_ "BLANK="
             if _<0|_>255 then call er 81,0 255 _ "BLANKS="
             blanks=d2c(_)
             end

if l==2 then do                      /* hexadecimal value.*/
             if \ishex(_) then call er 40,_
             blanks=x2c(_)
             end

if colors then tops='.P=1 .A=1 .C=green' tops      /*colors  used by $T.*/
if logs then tops='.F='gettfid(,"ANS") tops        /*logfile used by $T.*/
tops=space(tops)                                   /*options used by $T.*/

if n=='' then call er 54
if asayear   & ordinal then call er 61,'ASAYEAR ORDINAL'
if single    & ordinal then call er 61,'SINGLEY ORDINAL'
if american  & english then call er 61,'AMERICAN ENGLISH'
if american  & british then call er 61,'AMERICAN BRITISH'
if \american & \english & \british then american=1
if english then british=1

if clear then !cls                                 /*clear the screen ? */

dig.=;dig.0=zero;dig.1='one';dig.2='two';dig.3='three';dig.4='four';dig.5='five';dig.6='six';dig.7='seven';dig.8='eight';dig.9='nine'

_='0 thousand m b tr quadr quint sext sept oct non dec undec duodec tredec quattuordec quinquadec sedec septendec octodec novendec vigin unvigin duovigin tresvigin quattuorvigin quinquavigin sesvigin septemvigin octovigin novemvigin trigin'
_=_ 'untrigin duotrigin trestrigin quattuortrigin quinquatrigin sestrigin septentrigin octotrigin noventrigin quadragin unquadragin duoquadragin tresquadragin quattuorquadragin quinquaquadragin sesquadragin septenquadragin octoquadragin'
_=_ 'novenquadragin quinquagin unquinquagin duoquinquagin tresquinquagin quattuorquinquagin quinquaquinquagin sesquinquagin septenquinquagin octoquinquagin novenquinquagin sexagin unsexagin duosexagin tresexagin quattuorsexagin quinquasexagin'
_=_ 'sesexagin septensexagin octosexagin novensexagin septuagin unseptuagin duoseptuagin treseptuagin quattuorseptuagin quinquaseptuagin seseptuagin septenseptuagin octoseptuagin novenseptuagin octogin unoctogin duooctogin tresoctogin'
_=_ 'quattuoroctogin quinquaoctogin sexoctogin septemoctogin octooctogin novemoctogin nonagin unnonagin duononagin trenonagin quattuornonagin quinquanonagin senonagin septenonagin octononagin novenonagin cen uncen duocen trescen quattuorcen'
_=_ 'quinquacen sexcen septencen octocen novencen decicen undecicen duodecicen tredecicen quattuordecicen quinquadecicen sedecicen septendecicen octodecicen novendecicen viginticen unviginticen duoviginticen tresviginticen quattuorviginticen'
_=_ 'quinquaviginticen sesviginticen septemviginticen octoviginticen novemviginticen trigintacen untrigintacen duotrigintacen trestrigintacen quattuortrigintacen quinquatrigintacen sestrigintacen septentrigintacen octotrigintacen'
_=_ 'noventrigintacen quadragintacen unquadragintacen duoquadragintacen tresquadragintacen quattuorquadragintacen quinquaquadragintacen sesquadragintacen septenquadragintacen octoquadragintacen novenquadragintacen quinquagintacen'
_=_ 'unquinquagintacen duoquinquagintacen tresquinquagintacen quattuorquinquagintacen quinquaquinquagintacen sesquinquagintacen septenquinquagintacen octoquinquagintacen novenquinquagintacen sexagintacen unsexagintacen duosexagintacen'
_=_ 'tresexagintacen quattuorsexagintacen quinquasexagintacen sesexagintacen septensexagintacen octosexagintacen novensexagintacen septuagintacen unseptuagintacen duoseptuagintacen treseptuagintacen quattuorseptuagintacen quinquaseptuagintacen'
_=_ 'seseptuagintacen septenseptuagintacen octoseptuagintacen novenseptuagintacen octogintacen unoctogintacen duooctogintacen tresoctogintacen quattuoroctogintacen quinquaoctogintacen sexoctogintacen septemoctogintacen octooctogintacen'
_=_ 'novemoctogintacen nonagintacen unnonagintacen duononagintacen trenonagintacen quattuornonagintacen quinquanonagintacen senonagintacen septenonagintacen octononagintacen novenonagintacen ducen unducen duoducen treducen quattuorducen'
_=_ 'quinquaducen seducen septenducen octoducen novenducen deciducen undeciducen duodeciducen tredeciducen quattuordeciducen quinquadeciducen sedeciducen septendeciducen octodeciducen novendeciducen vigintiducen unvigintiducen duovigintiducen'
_=_ 'tresvigintiducen quattuorvigintiducen quinquavigintiducen sesvigintiducen septemvigintiducen octovigintiducen novemvigintiducen trigintaducen untrigintaducen duotrigintaducen trestrigintaducen quattuortrigintaducen quinquatrigintaducen'
_=_ 'sestrigintaducen septentrigintaducen octotrigintaducen noventrigintaducen quadragintaducen unquadragintaducen duoquadragintaducen tresquadragintaducen quattuorquadragintaducen quinquaquadragintaducen sesquadragintaducen'
_=_ 'septenquadragintaducen octoquadragintaducen novenquadragintaducen quinquagintaducen unquinquagintaducen duoquinquagintaducen tresquinquagintaducen quattuorquinquagintaducen quinquaquinquagintaducen sesquinquagintaducen'
_=_ 'septenquinquagintaducen octoquinquagintaducen novenquinquagintaducen sexagintaducen unsexagintaducen duosexagintaducen tresexagintaducen quattuorsexagintaducen quinquasexagintaducen sesexagintaducen septensexagintaducen octosexagintaducen'
_=_ 'novensexagintaducen septuagintaducen unseptuagintaducen duoseptuagintaducen treseptuagintaducen quattuorseptuagintaducen quinquaseptuagintaducen seseptuagintaducen septenseptuagintaducen octoseptuagintaducen novenseptuagintaducen'
_=_ 'octogintaducen unoctogintaducen duooctogintaducen tresoctogintaducen quattuoroctogintaducen quinquaoctogintaducen sexoctogintaducen septemoctogintaducen octooctogintaducen novemoctogintaducen nonagintaducen unnonagintaducen'
_=_ 'duononagintaducen trenonagintaducen quattuornonagintaducen quinquanonagintaducen senonagintaducen septenonagintaducen octononagintaducen novenonagintaducen trecen untrecen duotrecen trestrecen quattuortrecen quinquatrecen sestrecen'
_=_ 'septentrecen octotrecen noventrecen decitrecen undecitrecen duodecitrecen tredecitrecen quattuordecitrecen quinquadecitrecen sedecitrecen septendecitrecen octodecitrecen novendecitrecen vigintitrecen unvigintitrecen duovigintitrecen'
_=_ 'tresvigintitrecen quattuorvigintitrecen quinquavigintitrecen sesvigintitrecen septemvigintitrecen octovigintitrecen novemvigintitrecen trigintatrecen untrigintatrecen duotrigintatrecen trestrigintatrecen quattuortrigintatrecen'
_=_ 'quinquatrigintatrecen sestrigintatrecen septentrigintatrecen octotrigintatrecen noventrigintatrecen quadragintatrecen unquadragintatrecen duoquadragintatrecen tresquadragintatrecen quattuorquadragintatrecen quinquaquadragintatrecen'
_=_ 'sesquadragintatrecen septenquadragintatrecen octoquadragintatrecen novenquadragintatrecen quinquagintatrecen unquinquagintatrecen duoquinquagintatrecen tresquinquagintatrecen quattuorquinquagintatrecen quinquaquinquagintatrecen'
_=_ 'sesquinquagintatrecen septenquinquagintatrecen octoquinquagintatrecen novenquinquagintatrecen sexagintatrecen unsexagintatrecen duosexagintatrecen tresexagintatrecen quattuorsexagintatrecen quinquasexagintatrecen sesexagintatrecen'
_=_ 'septensexagintatrecen octosexagintatrecen novensexagintatrecen septuagintatrecen unseptuagintatrecen duoseptuagintatrecen treseptuagintatrecen quattuorseptuagintatrecen quinquaseptuagintatrecen seseptuagintatrecen septenseptuagintatrecen'
_=_ 'octoseptuagintatrecen novenseptuagintatrecen octogintatrecen unoctogintatrecen duooctogintatrecen tresoctogintatrecen quattuoroctogintatrecen quinquaoctogintatrecen sexoctogintatrecen septemoctogintatrecen octooctogintatrecen'
_=_ 'novemoctogintatrecen nonagintatrecen unnonagintatrecen duononagintatrecen trenonagintatrecen quattuornonagintatrecen quinquanonagintatrecen senonagintatrecen septenonagintatrecen octononagintatrecen novenonagintatrecen quadringen'
_=_ 'unquadringen duoquadringen tresquadringen quattuorquadringen quinquaquadringen sesquadringen septenquadringen octoquadringen novenquadringen deciquadringen undeciquadringen duodeciquadringen tredeciquadringen quattuordeciquadringen'
_=_ 'quinquadeciquadringen sedeciquadringen septendeciquadringen octodeciquadringen novendeciquadringen vigintiquadringen unvigintiquadringen duovigintiquadringen tresvigintiquadringen quattuorvigintiquadringen quinquavigintiquadringen'
_=_ 'sesvigintiquadringen septemvigintiquadringen octovigintiquadringen novemvigintiquadringen trigintaquadringen untrigintaquadringen duotrigintaquadringen trestrigintaquadringen quattuortrigintaquadringen quinquatrigintaquadringen'
_=_ 'sestrigintaquadringen septentrigintaquadringen octotrigintaquadringen noventrigintaquadringen quadragintaquadringen unquadragintaquadringen duoquadragintaquadringen tresquadragintaquadringen quattuorquadragintaquadringen'
_=_ 'quinquaquadragintaquadringen sesquadragintaquadringen septenquadragintaquadringen octoquadragintaquadringen novenquadragintaquadringen quinquagintaquadringen unquinquagintaquadringen duoquinquagintaquadringen tresquinquagintaquadringen'
_=_ 'quattuorquinquagintaquadringen quinquaquinquagintaquadringen sesquinquagintaquadringen septenquinquagintaquadringen octoquinquagintaquadringen novenquinquagintaquadringen sexagintaquadringen unsexagintaquadringen duosexagintaquadringen'
_=_ 'tresexagintaquadringen quattuorsexagintaquadringen quinquasexagintaquadringen sesexagintaquadringen septensexagintaquadringen octosexagintaquadringen novensexagintaquadringen septuagintaquadringen unseptuagintaquadringen'
_=_ 'duoseptuagintaquadringen treseptuagintaquadringen quattuorseptuagintaquadringen quinquaseptuagintaquadringen seseptuagintaquadringen septenseptuagintaquadringen octoseptuagintaquadringen novenseptuagintaquadringen octogintaquadringen'
_=_ 'unoctogintaquadringen duooctogintaquadringen tresoctogintaquadringen quattuoroctogintaquadringen quinquaoctogintaquadringen sexoctogintaquadringen septemoctogintaquadringen octooctogintaquadringen novemoctogintaquadringen'
_=_ 'nonagintaquadringen unnonagintaquadringen duononagintaquadringen trenonagintaquadringen quattuornonagintaquadringen quinquanonagintaquadringen senonagintaquadringen septenonagintaquadringen octononagintaquadringen novenonagintaquadringen'
_=_ 'quingen unquingen duoquingen tresquingen quattuorquingen quinquaquingen sesquingen septenquingen octoquingen novenquingen deciquingen undeciquingen duodeciquingen tredeciquingen quattuordeciquingen quinquadeciquingen sedeciquingen'
_=_ 'septendeciquingen octodeciquingen novendeciquingen vigintiquingen unvigintiquingen duovigintiquingen tresvigintiquingen quattuorvigintiquingen quinquavigintiquingen sesvigintiquingen septemvigintiquingen octovigintiquingen'
_=_ 'novemvigintiquingen trigintaquingen untrigintaquingen duotrigintaquingen trestrigintaquingen quattuortrigintaquingen quinquatrigintaquingen sestrigintaquingen septentrigintaquingen octotrigintaquingen noventrigintaquingen quadragintaquinge'
_=_ 'unquadragintaquingen duoquadragintaquingen tresquadragintaquingen quattuorquadragintaquingen quinquaquadragintaquingen sesquadragintaquingen septenquadragintaquingen octoquadragintaquingen novenquadragintaquingen quinquagintaquingen'
_=_ 'unquinquagintaquingen duoquinquagintaquingen tresquinquagintaquingen quattuorquinquagintaquingen quinquaquinquagintaquingen sesquinquagintaquingen septenquinquagintaquingen octoquinquagintaquingen novenquinquagintaquingen sexagintaquingen'
_=_ 'unsexagintaquingen duosexagintaquingen tresexagintaquingen quattuorsexagintaquingen quinquasexagintaquingen sesexagintaquingen septensexagintaquingen octosexagintaquingen novensexagintaquingen septuagintaquingen unseptuagintaquingen'
_=_ 'duoseptuagintaquingen treseptuagintaquingen quattuorseptuagintaquingen quinquaseptuagintaquingen seseptuagintaquingen septenseptuagintaquingen octoseptuagintaquingen novenseptuagintaquingen octogintaquingen unoctogintaquingen'
_=_ 'duooctogintaquingen tresoctogintaquingen quattuoroctogintaquingen quinquaoctogintaquingen sexoctogintaquingen septemoctogintaquingen octooctogintaquingen novemoctogintaquingen nonagintaquingen unnonagintaquingen duononagintaquingen'
_=_ 'trenonagintaquingen quattuornonagintaquingen quinquanonagintaquingen senonagintaquingen septenonagintaquingen octononagintaquingen novenonagintaquingen sescen unsescen duosescen tresescen quattuorsescen quinquasescen sesescen septensescen'
_=_ 'octosescen novensescen decisescen undecisescen duodecisescen tredecisescen quattuordecisescen quinquadecisescen sedecisescen septendecisescen octodecisescen novendecisescen vigintisescen unvigintisescen duovigintisescen tresvigintisescen'
_=_ 'quattuorvigintisescen quinquavigintisescen sesvigintisescen septemvigintisescen octovigintisescen novemvigintisescen trigintasescen untrigintasescen duotrigintasescen trestrigintasescen quattuortrigintasescen quinquatrigintasescen'
_=_ 'sestrigintasescen septentrigintasescen octotrigintasescen noventrigintasescen quadragintasescen unquadragintasescen duoquadragintasescen tresquadragintasescen quattuorquadragintasescen quinquaquadragintasescen sesquadragintasescen'
_=_ 'septenquadragintasescen octoquadragintasescen novenquadragintasescen quinquagintasescen unquinquagintasescen duoquinquagintasescen tresquinquagintasescen quattuorquinquagintasescen quinquaquinquagintasescen sesquinquagintasescen'
_=_ 'septenquinquagintasescen octoquinquagintasescen novenquinquagintasescen sexagintasescen unsexagintasescen duosexagintasescen tresexagintasescen quattuorsexagintasescen quinquasexagintasescen sesexagintasescen septensexagintasescen'
_=_ 'octosexagintasescen novensexagintasescen septuagintasescen unseptuagintasescen duoseptuagintasescen treseptuagintasescen quattuorseptuagintasescen quinquaseptuagintasescen seseptuagintasescen septenseptuagintasescen octoseptuagintasescen'
_=_ 'novenseptuagintasescen octogintasescen unoctogintasescen duooctogintasescen tresoctogintasescen quattuoroctogintasescen quinquaoctogintasescen sexoctogintasescen septemoctogintasescen octooctogintasescen novemoctogintasescen nonagintasesce'
_=_ 'unnonagintasescen duononagintasescen trenonagintasescen quattuornonagintasescen quinquanonagintasescen senonagintasescen septenonagintasescen octononagintasescen novenonagintasescen septingen unseptingen duoseptingen treseptingen'
_=_ 'quattuorseptingen quinquaseptingen seseptingen septenseptingen octoseptingen novenseptingen deciseptingen undeciseptingen duodeciseptingen tredeciseptingen quattuordeciseptingen quinquadeciseptingen sedeciseptingen septendeciseptingen'
_=_ 'octodeciseptingen novendeciseptingen vigintiseptingen unvigintiseptingen duovigintiseptingen tresvigintiseptingen quattuorvigintiseptingen quinquavigintiseptingen sesvigintiseptingen septemvigintiseptingen octovigintiseptingen'
_=_ 'novemvigintiseptingen trigintaseptingen untrigintaseptingen duotrigintaseptingen trestrigintaseptingen quattuortrigintaseptingen quinquatrigintaseptingen sestrigintaseptingen septentrigintaseptingen octotrigintaseptingen'
_=_ 'noventrigintaseptingen quadragintaseptingen unquadragintaseptingen duoquadragintaseptingen tresquadragintaseptingen quattuorquadragintaseptingen quinquaquadragintaseptingen sesquadragintaseptingen septenquadragintaseptingen'
_=_ 'octoquadragintaseptingen novenquadragintaseptingen quinquagintaseptingen unquinquagintaseptingen duoquinquagintaseptingen tresquinquagintaseptingen quattuorquinquagintaseptingen quinquaquinquagintaseptingen sesquinquagintaseptingen'
_=_ 'septenquinquagintaseptingen octoquinquagintaseptingen novenquinquagintaseptingen sexagintaseptingen unsexagintaseptingen duosexagintaseptingen tresexagintaseptingen quattuorsexagintaseptingen quinquasexagintaseptingen sesexagintaseptingen'
_=_ 'septensexagintaseptingen octosexagintaseptingen novensexagintaseptingen septuagintaseptingen unseptuagintaseptingen duoseptuagintaseptingen treseptuagintaseptingen quattuorseptuagintaseptingen quinquaseptuagintaseptingen'
_=_ 'seseptuagintaseptingen septenseptuagintaseptingen octoseptuagintaseptingen novenseptuagintaseptingen octogintaseptingen unoctogintaseptingen duooctogintaseptingen tresoctogintaseptingen quattuoroctogintaseptingen quinquaoctogintaseptingen'
_=_ 'sexoctogintaseptingen septemoctogintaseptingen octooctogintaseptingen novemoctogintaseptingen nonagintaseptingen unnonagintaseptingen duononagintaseptingen trenonagintaseptingen quattuornonagintaseptingen quinquanonagintaseptingen'
_=_ 'senonagintaseptingen septenonagintaseptingen octononagintaseptingen novenonagintaseptingen octingen unoctingen duooctingen tresoctingen quattuoroctingen quinquaoctingen sexoctingen septemoctingen octooctingen novemoctingen decioctingen'
_=_ 'undecioctingen duodecioctingen tredecioctingen quattuordecioctingen quinquadecioctingen sedecioctingen septendecioctingen octodecioctingen novendecioctingen vigintioctingen unvigintioctingen duovigintioctingen tresvigintioctingen'
_=_ 'quattuorvigintioctingen quinquavigintioctingen sesvigintioctingen septemvigintioctingen octovigintioctingen novemvigintioctingen trigintaoctingen untrigintaoctingen duotrigintaoctingen trestrigintaoctingen quattuortrigintaoctingen'
_=_ 'quinquatrigintaoctingen sestrigintaoctingen septentrigintaoctingen octotrigintaoctingen noventrigintaoctingen quadragintaoctingen unquadragintaoctingen duoquadragintaoctingen tresquadragintaoctingen quattuorquadragintaoctingen'
_=_ 'quinquaquadragintaoctingen sesquadragintaoctingen septenquadragintaoctingen octoquadragintaoctingen novenquadragintaoctingen quinquagintaoctingen unquinquagintaoctingen duoquinquagintaoctingen tresquinquagintaoctingen'
_=_ 'quattuorquinquagintaoctingen quinquaquinquagintaoctingen sesquinquagintaoctingen septenquinquagintaoctingen octoquinquagintaoctingen novenquinquagintaoctingen sexagintaoctingen unsexagintaoctingen duosexagintaoctingen tresexagintaoctingen'
_=_ 'quattuorsexagintaoctingen quinquasexagintaoctingen sesexagintaoctingen septensexagintaoctingen octosexagintaoctingen novensexagintaoctingen septuagintaoctingen unseptuagintaoctingen duoseptuagintaoctingen treseptuagintaoctingen'
_=_ 'quattuorseptuagintaoctingen quinquaseptuagintaoctingen seseptuagintaoctingen septenseptuagintaoctingen octoseptuagintaoctingen novenseptuagintaoctingen octogintaoctingen unoctogintaoctingen duooctogintaoctingen tresoctogintaoctingen'
_=_ 'quattuoroctogintaoctingen quinquaoctogintaoctingen sexoctogintaoctingen septemoctogintaoctingen octooctogintaoctingen novemoctogintaoctingen nonagintaoctingen unnonagintaoctingen duononagintaoctingen trenonagintaoctingen'
_=_ 'quattuornonagintaoctingen quinquanonagintaoctingen senonagintaoctingen septenonagintaoctingen octononagintaoctingen novenonagintaoctingen nongen unnongen duonongen trenongen quattuornongen quinquanongen senongen septenongen octonongen'
_=_ 'novenongen decinongen undecinongen duodecinongen tredecinongen quattuordecinongen quinquadecinongen sedecinongen septendecinongen octodecinongen novendecinongen vigintinongen unvigintinongen duovigintinongen tresvigintinongen'
_=_ 'quattuorvigintinongen quinquavigintinongen sesvigintinongen septemvigintinongen octovigintinongen novemvigintinongen trigintanongen untrigintanongen duotrigintanongen trestrigintanongen quattuortrigintanongen quinquatrigintanongen'
_=_ 'sestrigintanongen septentrigintanongen octotrigintanongen noventrigintanongen quadragintanongen unquadragintanongen duoquadragintanongen tresquadragintanongen quattuorquadragintanongen quinquaquadragintanongen sesquadragintanongen'
_=_ 'septenquadragintanongen octoquadragintanongen novenquadragintanongen quinquagintanongen unquinquagintanongen duoquinquagintanongen tresquinquagintanongen quattuorquinquagintanongen quinquaquinquagintanongen sesquinquagintanongen'
_=_ 'septenquinquagintanongen octoquinquagintanongen novenquinquagintanongen sexagintanongen unsexagintanongen duosexagintanongen tresexagintanongen quattuorsexagintanongen quinquasexagintanongen sesexagintanongen septensexagintanongen'
_=_ 'octosexagintanongen novensexagintanongen septuagintanongen unseptuagintanongen duoseptuagintanongen treseptuagintanongen quattuorseptuagintanongen quinquaseptuagintanongen seseptuagintanongen septenseptuagintanongen octoseptuagintanongen'
_=_ 'novenseptuagintanongen octogintanongen unoctogintanongen duooctogintanongen tresoctogintanongen quattuoroctogintanongen quinquaoctogintanongen sexoctogintanongen septemoctogintanongen octooctogintanongen novemoctogintanongen nonagintanonge'
_=_ 'unnonagintanongen duononagintanongen trenonagintanongen quattuornonagintanongen quinquanonagintanongen senonagintanongen septenonagintanongen novenonagintanongen octononagintanongen'

amers=words(_)
  do j=1 for amers; a.j=word(_,j); end
maxzlen=amers *3
if british then do
                engs=amers*2-2; maxzlen=engs*3
                  do k=1 for 2; b.k=a.k; end
                  do j=3 to amers; _=j*2-3; b._=a.j; _n=_+1; b._n=a.j; end
                drop a.
                end

D:\►type sp2.rex
n=space(n); _=left(n,1)
sig=
if _=='-' | _=="+" then do                 /*handle leading sign (+ -).*/
                        if _=='+' then sig=plus
                                  else sig=minus
                        n=substr(n,2)      /*remove the leading sign.  */
                        end
numeric digits 80+maxzlen
zpoints =countstr('.',n); zpoint =zpoints \==0; if zpoints >1 then call er 59,'decimal-points(.)'
zdollars=countstr('$',n); zdollar=zdollars\==0; if zdollars>1 then call er 59,'dollar-signs($)'
zeuros  =countstr('ε',n); zeuro  =zeuros  \==0; if zeuros  >1 then call er 59,'euro-signs(ε)'
zfrancs =countstr('ƒ',n); zfranc =zfrancs \==0; if zfrancs >1 then call er 59,'franc-signs(ƒ)'
zpounds =countstr('£',n); zpound =zpounds \==0; if zpounds >1 then call er 59,'pound-signs(£)'
zyens   =countstr('¥',n); zyen   =zyens   \==0; if zyens   >1 then call er 59,'yen-signs(¥)'
zpisetas=countstr('₧',n); zpiseta=zpisetas\==0; if zpisetas>1 then call er 59,'piseta-signs(₧)'
zcents  =countstr('¢',n); zcent  =zcents  \==0; if zcents  >1 then call er 59,'cent-signs(¢)'
zcurrs=zdollars+zeuros+zpounds+zyens+zpisetas+zfrancs+zcents
zcurr=zcurrs\==0
if zcurrs>2 then call er 59,'currency symbols'
if zdollar  then do; xcurr=dollar; n=changestr("$",n,''); end
if zeuro    then do; xcurr=euro;   n=changestr("ε",n,''); end
if zpound   then do; xcurr=pound;  n=changestr("£",n,''); end
if zyen     then do; xcurr=yen;    n=changestr("¥",n,''); end
if zpiseta  then do; xcurr=piseta; n=changestr("₧",n,''); end
if zfranc   then do; xcurr=franc;  n=changestr("ƒ",n,''); end
if zcent    then do; xcurr=cent;   n=changestr("¢",n,''); end

if zpoint then dot=point                 /*we have a decimal point.     */
_=right(n,1)                             /*pick off right-most character*/
if ismix(_) | _=='!' then n=num(n)       /*if # has a suffix, convert it*/
parse upper var n n 'E' exponent         /*parse the exponent, if any.  */
parse var n n '.' fraction
leadzs=compare(n,copies(0,digits()))-1   /*count leading zeroes.*/
n=changestr(',',n,"")

if isnum(n) then do
                 if \asis then n=n/1
                 end
            else do 1
                 if n=='' then leave
                 expression=n
                 interpret 'number='expression
                 n=trunc(number)
                 end

if xcurr\=='' then do 1
                   if xcurr==zyen then leave
                   if n\==1 then xcurr=xcurr's'
                   end

max#=10**maxzlen*1000-1
if \asis  & isnum(n)  then n=n/1
if n\=='' & isnum(n)  then if n>max# then call er 81,-max# max# ogn
if n\=='' & \isint(n) then call er 53,n
if abs(n)>max#        then call er 81,-max# max# ogn
if leading\==''       then leadingz=copies(leading' ',leadzs)

if asayear & right(n,3)\==000 then do
                                   #=spnte(left(n,max(0,length(n)-2)))
                                   if #==zero then #=
                                   _2=right(n,2)
                                   _=spnte(_2)
                                   if _==zero then _="hundred"
                                   if _2<10 & _2>0 then _=zero _
                                   #=sig||# _
                                   end
                              else #=sig||leadingz||spnte(n)

if ordinal then
   do
   sx=;w=words(#);p=word(#,w);oldp=p;pp=
   if pos('-',p)\==0 then parse var p pp '-'p
   if pp\=='' then pp=pp'-'
        select
        when p=='one'    then p="first"
        when p=='two'    then p="second"
        when p=='three'  then p="third"
        when p=='five'   then p="fifth"
        when p=='eight'  then p="eighth"
        when p=='nine'   then p="ninth"
        when p=='twelve' then p="twelfth"
        when right(p,1)=='y' then p=left(p,length(p)-1)"ieth"
        otherwise sx='th'
        end
   if p\==oldp then if w==1 then #=pp||p
                            else #=subword(#,1,w-1) pp||p
   #=#||sx
   end

lf=length(fraction)
if (lf==1 | lf==2) & zdollar then do
                                  if fraction\=1 then cent=cent's'
                                  fractions=sp(fraction) cent
                                  dot=xcurr andcent
                                  xcurr=
                                  end
                             else do j=1 for lf
                                  _=substr(fraction,j,1)
                                  fractions=fractions dig._
                                  end
if exponent\=='' then
   do
   if \isint(exponent) then call er 53,exponent 'exponent'
   _=sp(exponent "ORDINAL");if _\=='' then exponents=raised _ power
   end

after=space(dot fractions exponents xcurr)
if after\=='' then after=" "after
#=translate(#||after,,"_");if blanks\=='' then #=translate(#,blanks," ")
if \quiet then call $t tops #
if !fun=='COMMAND' then return 0
return #

/*─────────────────────────────spnte subroutine─────────────────────────*/
spnte: parse arg zz; if zz==0 | zz=' ' then return nothing; en=
bzz=reverse(zz)
                has_t=22
if british then has_t=41

if single then do j=1 for length(zz)
               _=substr(zz,j,1);en=en dig._
               end

          else do j=1 to maxzlen by 3
               _=(j+2)%3
               if american then zillion=a._
                           else zillion=b._
               if zillion==0 then zillion=
               if _>=has_t then zillion=zillion't'

               if _>2 then do
                           if american then zillion=zillion'illion'
                                       else if _//2 then zillion=zillion'illion'
                                                    else zillion=zillion'illiard'
                           end

               ttt=reverse(substr(bzz,j,3)); if ttt=='   ' then leave
               ttt=right(strip(ttt),3,0)   ; if ttt== 000  then iterate
               x=sphtu(ttt) zillion
               if en\=='' then en=sep||en;en=x en
               end

en=strip(translate(en,,"_"))
if en=='' then if zcurr then do;if \zcent then en="no";end
                        else en=zero
return en

/*─────────────────────────────sphtu subroutine─────────────────────────*/
sphtu: procedure; parse arg z
@987='nine eight seven six five four three two one'
zm=substr(z,2,1)
zr=right(z,1)
zh=word(@987,10-left(z,1))
if zh\=='' then zh=zh "hundred"
zt=word('ninety eighty seventy sixty fifty forty thirty twenty',10-zm)
zu=word(@987,10-zr)
@teens='ten eleven twelve thir four fif six seven eigh nine'
if zm==1 then do
              zu=
              zt=word(@teens,zr+1)
              if zr>2 then zt=zt'teen'
              end
if zt\=='' & zu\=="" then do
                          zt=zt'-'zu
                          zu=
                          end
return space(zh zt zu)

/*═════════════════════════════general 1-line subs══════════════════════*/
!all:!!=!;!=space(!);upper !;call !fid;!nt=right(!var('OS'),2)=='NT';!cls=word('CLS VMFCLEAR CLRSCREEN',1+!cms+!tso*2);if arg(1)\==1 then return 0;if wordpos(!,'? ?SAMPLES ?AUTHOR ?FLOW')==0 then return 0;!call=']$H';call '$H' !fn !;!call=;return 1
!cal:if symbol('!CALL')\=="VAR" then !call=;return !call
!env:!env='ENVIRONMENT';if !sys=='MSDOS'|!brexx|!r4|!roo then !env='SYSTEM';if !os2 then !env='OS2'!env;!ebcdic=1=='f0'x;return
!fid:parse upper source !sys !fun !fid . 1 . . !fn !ft !fm .;call !sys;if !dos then do;_=lastpos('\',!fn);!fm=left(!fn,_);!fn=substr(!fn,_+1);parse var !fn !fn '.' !ft;end;return word(0 !fn !ft !fm,1+('0'arg(1)))
!rex:parse upper version !ver !vernum !verdate .;!brexx='BY'==!vernum;!kexx='KEXX'==!ver;!pcrexx='REXX/PERSONAL'==!ver|'REXX/PC'==!ver;!r4='REXX-R4'==!ver;!regina='REXX-REGINA'==left(!ver,11);!roo='REXX-ROO'==!ver;call !env;return
!sys:!cms=!sys=='CMS';!os2=!sys=='OS2';!tso=!sys=='TSO'|!sys=='MVS';!vse=!sys=='VSE';!dos=pos('DOS',!sys)\==0|pos('WIN',!sys)\==0|!sys=='CMD';call !rex;return
!var:call !fid;if !kexx then return space(dosenv(arg(1)));return space(value(arg(1),,!env))
$fact!:procedure;parse arg x _ .;l=length(x);n=l-length(strip(x,'T',"!"));if n==0|_\==''|arg()\==1 then return x;z=left(x,l-n);if z<0|\datatype(z,'W') then return x;return $fact(z,n)
$fact:procedure;parse arg x _ .;arg ,n ! .;n=p(n 1);if \isint(n) then n=0;if x<0|\isint(x)|n<1|_||!\==''|arg()>2 then return x||copies("!",max(1,n));!=1;s=x//n;if s==0 then s=n;do j=s to x by n;!=!*j;end;return !
$sfxa:parse arg ,s,m;arg u,c;if pos(left(s,2),u)\==0 then do j=length(s) to compare(s,c)-1 by -1;if right(u,j)\==left(c,j) then iterate;_=left(u,length(u)-j);if datatype(_,'N') then return m*_;leave;end;return arg(1)
$sfxf:parse arg y;if right(y,1)=='!' then y=$fact!(y);if \datatype(y,'N') then y=$sfxz();if datatype(y,'N') then return y;return $sfxm(y)
$sfxm:parse arg z;arg w;b=1000;if right(w,1)=='I' then do;z=shorten(z);w=z;upper w;b=1024;end;p=pos(right(w,1),'KMGTPEZYXWVU');if p==0 then return arg(1);n=shorten(z);r=num(n,f,1);if datatype(r,'N') then return r*b**p;return arg(1)
$sfxz:return $sfxa($sfxa($sfxa($sfxa($sfxa($sfxa(y,'PAIRs',2),'DOZens',12),'SCore',20),'GREATGRoss',1728),'GRoss',144),'GOOGOLs',1e100)

$t: say arg(1); return    /*this label pre-empts the one below*/
/*$T (below) supports many options: color(s), writing the output to a file, and many others. */
$t:!call=']$T';call "$T" arg(1);!call=;return

abb:arg abbu;parse arg abb;return abbrev(abbu,_,abbl(abb))
abbl:return verify(arg(1)'a',@abc,'M')-1
abbn:parse arg abbn;return abb(abbn)|abb('NO'abbn)
changestr:procedure;parse arg o,h,n;r=;w=length(o);if w==0 then return n||h;do forever;parse var h y (o) _ +(w) h;if _=='' then return r||y;r=r||y||n;end
countstr:procedure;parse arg n,h,s;if s=='' then s=1;w=length(n);do r=0 until _==0;_=pos(n,h,s);s=_+w;end;return r
er:parse arg _1,_2;call '$ERR' "14"p(_1) p(word(_1,2) !fid(1)) _2;if _1<0 then return _1;exit result
err:call er '-'arg(1),arg(2);return ''
erx:call er '-'arg(1),arg(2);exit ''
getdtfid:tfid=p(!var("TMP") !var('TEMP') homedrive()"\");if substr(tfid,2,1)==':'&substr(tfid,3,1)\=="\" then tfid=insert('\',t,2);return strip(tfid,'T',"\")'\'arg(1)'.'arg(2)
gettfid:if tfid\=='' then return tfid;gfn=word(arg(1) !fn,1);gft=word(arg(2) 'ANS',1);tfid='TEMP';if !tso then tfid=gfn'.'gft;if !cms then tfid=gfn','gft",A4";if !dos then tfid=getdtfid(gfn,gft);return tfid
halt:call er .1
homedrive:if symbol('HOMEDRIVE')\=="VAR" then homedrive=p(!var('HOMEDRIVE') 'C:');return homedrive
int:int=num(arg(1),arg(2));if \isint(int) then call er 92,arg(1) arg(2);return int/1
ishex:return datatype(arg(1),'X')
isint:return datatype(arg(1),'W')
ismix:return datatype(arg(1),'M')
isnum:return datatype(arg(1),'N')
na:if arg(1)\=='' then call er 01,arg(2);parse var ops na ops;if na=='' then call er 35,_o;return na
nai:return int(na(),_o)
nan:return num(na(),_o)
no:if arg(1)\=='' then call er 01,arg(2);return left(_,2)\=='NO'
novalue:!sigl=sigl;call er 17,!fid(2) !fid(3) !sigl condition('D') sourceline(!sigl)
num:procedure;parse arg x .,f,q;if x=='' then return x;if datatype(x,'N') then return x/1;x=space(translate(x,,','),0);if \datatype(x,'N') then x=$sfxf(x);if datatype(x,'N') then return x/1;return numnot()
numnot:if q==1 then return x;if q=='' then call er 53,x f;call erx 53,x f
p:return word(arg(1),1)
shorten:procedure;parse arg a,n;return left(a,max(0,length(a)-p(n 1)))
sp:!call=']'!fn;sp="$SPELL#"(arg(1) 'Q');!call=;return sp
syntax:!sigl=sigl;call er 13,!fid(2) !fid(3) !sigl !cal() condition('D') sourceline(!sigl)

output

Output  when using the input of: 373 ordinal
three hundred seventy-third

Output  when using the input of: 373
three hundred seventy-three

Output  when using the input of: +45
plus forty-five

Output  when using the input of: 1989 asYear
nineteen eighty-nine

Output  when using the input of: -12.79
minus twelve point seven nine

Output  when using the input of: $119.63
one hundred nineteen dollars and sixty-three cents

Output  when using the input of: 3456T
three quadrillion four hundred fifty-six trillion

Output  when using the input of: 4Ki
four thousand ninety-six

Output  when using the input of: 6!
seven hundred twenty

Output  when using the input of: 10dozen
one hundred twenty

Output  when using the input of: 70000000000000...(3,000 zeroes total)
seven octononagintanongentillion

Ruby

Translation of: Python
Works with: Ruby version 1.8.7+

<lang ruby>def spell_integer(n)

 tens = [nil, nil, "twenty", "thirty", "forty",
         "fifty", "sixty", "seventy", "eighty", "ninety"]
 small = ["zero", "one", "two", "three", "four", "five",
           "six", "seven", "eight", "nine", "ten", "eleven",
           "twelve", "thirteen", "fourteen", "fifteen",
           "sixteen", "seventeen", "eighteen", "nineteen"]
 def nonzero(c, n)
   n.zero? ?  "" : c + spell_integer(n)
 end
 def big(e, n)
   bl = [nil, nil, "m", "b", "tr", "quadr",
         "quint", "sext", "sept", "oct", "non", "dec"]
   if    e >= bl.length then raise ArgumentError, "value too large to represent"
   elsif e == 0         then spell_integer(n)
   elsif e == 1         then spell_integer(n) + " thousand"
   else
     spell_integer(n) + " " + bl[e] + "illion"
   end
 end
 def base1000_rev(n)
   # returns the value of the digits of n in base 1000
   # (i.e. 3-digit chunks), in reverse.
   chunks = []
   while n != 0
     n, r = n.divmod(1000)
     chunks << r
   end
   chunks
 end
 if    n < 0    then "negative " + spell_integer(n.abs)
 elsif n < 20   then small[n]
 elsif n < 100  then a, b = n.divmod(10); tens[a] + nonzero("-", b)
 elsif n < 1000 then a, b = n.divmod(100); small[a] + " hundred" + nonzero(" ", b)
 else
   base1000_rev(n).each_with_index \
                  .find_all {|val, idx| val.nonzero?} \
                  .map {|val, idx| big(idx, val)} \
                  .reverse \
                  .join(', ')
 end

end

  1. example

for test in [0, -0, 5, -5, 25, 90, 100, 101, 999, 1000, 1008, 54321, 1234567890, 0x7F,

            123456789012345678901234567890123456, 1234567890123456789012345678901234567]
 print "#{test} -> "
 begin
   puts spell_integer(test)
 rescue => e
   puts "Error: #{e}"
 end

end</lang>

0 -> zero
0 -> zero
5 -> five
-5 -> negative five
25 -> twenty-five
90 -> ninety
100 -> one hundred
101 -> one hundred one
999 -> nine hundred ninety-nine
1000 -> one thousand
1008 -> one thousand, eight
54321 -> fifty-four thousand, three hundred twenty-one
1234567890 -> one billion, two hundred thirty-four million, five hundred sixty-seven thousand, eight hundred ninety
127 -> one hundred twenty-seven
123456789012345678901234567890123456 -> one hundred twenty-three decillion, four hundred fifty-six nonillion, seven hundred eighty-nine octillion, twelve septillion, three hundred forty-five sextillion, six hundred seventy-eight quintillion, nine hundred one quadrillion, two hundred thirty-four trillion, five hundred sixty-seven billion, eight hundred ninety million, one hundred twenty-three thousand, four hundred fifty-six
1234567890123456789012345678901234567 -> Error: value too large to represent

Tcl

<lang tcl>proc int2words {n} {

   if { ! [regexp -- {^(-?\d+)$} $n -> n]} {
       error "not a decimal integer"
   }
   if {$n == 0} {
       return zero
   }
   if {$n < 0} {
       return "negative [int2words [expr {abs($n)}]]"
   }
   if {[string length $n] > 36} {
       error "value too large to represent"
   }
   
   set groups [get_groups $n]
   set l [llength $groups]
   foreach group $groups {
       incr l -1
       # ensure any group with a leading zero is not treated as octal
       set val [scan $group %d]
       if {$val > 0} {
           lappend result [group2words $val $l]
       }
   }
   return [join $result ", "]

}

set small {"" one two three four five six seven eight nine ten eleven twelve

          thirteen fourteen fifteen sixteen seventeen eighteen nineteen}

set tens {"" "" twenty thirty forty fifty sixty seventy eighty ninety} set powers {"" thousand} foreach p {m b tr quadr quint sext sept oct non dec} {lappend powers ${p}illion}

proc group2words {n level} {

   global small tens powers
   if {$n < 20} {
       lappend result [lindex $small $n]
   } elseif {$n < 100} {
       lassign [divmod $n 10] a b
       set result [lindex $tens $a]
       if {$b > 0} {
           append result - [lindex $small $b]
       }
   } else {
       lassign [divmod $n 100] a b
       lappend result [lindex $small $a] hundred
       if {$b > 0} {
           lappend result and [group2words $b 0]
       }
   }
   return [join [concat $result [lindex $powers $level]]]

}

proc divmod {n d} {

   return [list [expr {$n / $d}] [expr {$n % $d}]]

}

proc get_groups {num} {

   # from http://wiki.tcl.tk/5000
   while {[regsub {^([-+]?\d+)(\d\d\d)} $num {\1 \2} num]} {}
   return [split $num]

}

foreach test {

       0 -0 5 -5 10 25 99 100 101 999 1000 1008 1010 54321 1234567890
       0x7F
       123456789012345678901234567890123456
       1234567890123456789012345678901234567

} {

   catch {int2words $test} result
   puts "$test -> $result"

}</lang> produces

0 -> zero
-0 -> zero
5 -> five
-5 -> negative five
10 -> ten
25 -> twenty-five
99 -> ninety-nine
100 -> one hundred
101 -> one hundred and one
999 -> nine hundred and ninety-nine
1000 -> one thousand
1008 -> one thousand, eight
1010 -> one thousand, ten
54321 -> fifty-four thousand, three hundred and twenty-one
1234567890 -> one billion, two hundred and thirty-four million, five hundred and sixty-seven thousand, eight hundred and ninety
0x7F -> not a decimal integer
123456789012345678901234567890123456 -> one hundred and twenty-three decillion, four hundred and fifty-six nonillion, seven hundred and eighty-nine octillion, twelve septillion, three hundred and forty-five sextillion, six hundred and seventy-eight quintillion, nine hundred and one quadrillion, two hundred and thirty-four trillion, five hundred and sixty-seven billion, eight hundred and ninety million, one hundred and twenty-three thousand, four hundred and fifty-six
1234567890123456789012345678901234567 -> value too large to represent

Visual Basic

Translation of: BASIC

If one were to use variants further and get them to play nice as Decimal, this could theoretically be extended up to the octillion range. <lang vb>Option Explicit

Private small As Variant, tens As Variant, big As Variant

Sub Main()

   small = Array("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", _
                 "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", _
                 "eighteen", "nineteen")
   tens = Array("twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety")
   big = Array("thousand", "million", "billion")
   Dim tmpInt As Long
   tmpInt = Val(InputBox("Gimme a number!", "NOW!", Trim$(Year(Now)) & IIf(Month(Now) < 10, "0", "") & _
                Trim$(Month(Now)) & IIf(Day(Now) < 10, "0", "") & Trim$(Day(Now))))
   MsgBox int2Text$(tmpInt)

End Sub

Function int2Text$(number As Long)

   Dim num As Long, outP As String, unit As Integer
   Dim tmpLng1 As Long
   If 0 = number Then
       int2Text$ = "zero"
       Exit Function
   End If
   num = Abs(number)
   Do
       tmpLng1 = num Mod 100
       Select Case tmpLng1
           Case 1 To 19
               outP = small(tmpLng1 - 1) + " " + outP
           Case 20 To 99
               Select Case tmpLng1 Mod 10
                   Case 0
                       outP = tens((tmpLng1 \ 10) - 2) + " " + outP
                   Case Else
                       outP = tens((tmpLng1 \ 10) - 2) + "-" + small(tmpLng1 Mod 10) + " " + outP
               End Select
       End Select
       tmpLng1 = (num Mod 1000) \ 100
       If tmpLng1 Then
           outP = small(tmpLng1 - 1) + " hundred " + outP
       End If
       num = num \ 1000
       If num < 1 Then Exit Do
       tmpLng1 = num Mod 1000
       If tmpLng1 Then outP = big(unit) + " " + outP
       unit = unit + 1
   Loop
   If number < 0 Then outP = "negative " & outP
   int2Text$ = Trim$(outP)

End Function</lang>

Example output (in a msgbox) is identical to the BASIC output.

Visual Basic .NET

Platform: .NET

Works with: Visual Basic .NET version 9.0+

This solution works for integers up to 1000. It should be fairly ovbious how it works, and so can be extended if needed.

<lang vbnet>Module Module1

   Sub Main()
       Dim i As Integer
       Console.WriteLine("Enter a number")
       i = Console.ReadLine()
       Console.WriteLine(words(i))
       Console.ReadLine()
   End Sub
   
   Function words(ByVal Number As Integer) As String
       Dim small() As String = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
        "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen",
        "eighteen", "nineteen"}
       Dim tens() As String = {"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"}
       Select Case Number
           Case Is < 20
               words = small(Number)
           Case 20 To 99
               words = tens(Number \ 10) + " " + small(Number Mod 10)
           Case 100 To 999
               words = small(Number \ 100) + " hundred " + IIf(((Number Mod 100) <> 0), "and ", "") + words(Number Mod 100)
           Case 1000
               words = "one thousand"
       End Select
   End Function

End Module</lang>