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
<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</lang>
<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));
- 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
<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
This uses the code from Basic string manipulation functions. <lang c>#include <stdio.h>
- include "estrings.h"
- define setStringFromCStr(S, N) setString((S), (N), strlen(N))
- 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;
}
- 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>
- 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() {
- 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
<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) )
- 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.
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 j> 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</lang>
Java
<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
Logo
<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>
Perl
<lang perl>use Lingua::EN::Numbers 'num2en';
print num2en(123456789), "\n";</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
<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])
- 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
Ruby
<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 raise ArgumentError, "spell_integer: negative input" 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
- 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 -> Error: spell_integer: negative input 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
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
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>