Number names: Difference between revisions
Underscore (talk | contribs) (Deleted AutoHotkey. If the example referred to is ever retrieved, it can be put here in place of the incorrect solution.) |
m (→[[Number names#ALGOL 68]]: fix a missing CASE OUT, add GOTO to make compatable with official ALGOL 68 subset.) |
||
Line 137:
=={{header|ALGOL 68}}==
<!-- # From: www.codecodex.com/wiki/index.php%3Ftitle%3DConvert_an_integer_into_words - site states it is GPL # -->
{{works with|ALGOL 68|Standard - no extensions to language used}}
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-1.18.0/algol68g-1.18.0-9h.tiny.el5.centos.fc11.i386.rpm/download 1.18.0-9h.tiny]}}
{{works with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8.8d.fc9.i386]}}
<lang algol68>PROC number words = (INT n)STRING:(
# returns a string representation of n in words. Currently
Line 146 ⟶ 151:
[]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. #
Line 152 ⟶ 157:
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]|"")
);
Line 164 ⟶ 169:
(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;
|
Revision as of 22:54, 21 March 2010
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: <lang algol68>n? 43112609 forty-three million, one hundred and twelve thousand, six hundred and nine</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>
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>
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>
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)</lang>
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: raise ArgumentError, "value too large to represent" elsif e == 0 : spell_integer(n) elsif e == 1 : 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 : raise ArgumentError, "spell_integer: negative input" elsif n < 20 : small[n] elsif n < 100 : a, b = n.divmod(10); tens[a] + nonzero("-", b) elsif n < 1000: 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>