This solution is similar in spirit to Prashant's. Though not particularly elegant, I avoid any calls to W|A and any other form of internet connectivity. Further down the post I also provide a solution to the inverse problem of returning the number when given English words.
numberform[n_]:=With[{id=IntegerDigits@n},
Partition[PadLeft[id,3Ceiling[Length[id]/3]],3]]
single={"One","Two","Three","Four","Five","Six","Seven","Eight","Nine"};
teen= {"Ten","Eleven","Twelve","Thirteen","Fourteen","Fifteen",
"Sixteen","Seventeen","Eighteen","Nineteen"};
double={"Twenty","Thirty","Forty","Fifty","Sixty","Seventy","Eighty","Ninety"};
big= {"Thousand","Million","Billion","Trillion","Quadrillion",
"Quintillion","Sextillion","Septillion","Octillion","Nonillion",
"Decillion","Undecillion","Duodecillion","Tredecillion",
"Quattuordecillion","Quindecillion","Sexdecillion",
"Septendecillion","Octodecillion","Novemdecillion","Vigintillion"};
ones[o_]:=Replace[o,Thread[Join[Range[9],{_}]->Join[single,{""}]]]
tens[t_,o_]:=
Switch[t,0,ones[o],1,Replace[o,Thread[Range[0,9]->teen]],
_,Replace[t,Thread[Range[2,9]->double]]<>
If[o==0,""," "<>ones[o]]]
hundreds[arg:{h_,t_,o_}]:=
Switch[arg,{0,0,0},"",{0,0,_},ones[o],{0,_,_},tens[t,o],_,ones[h]<>
" Hundred "<>tens[t,o]]
createBlock[b_,n_]:=If[MatchQ[b,""],"",b<>" "<>
Switch[n,1,"",x_/;x<=22,big[[n-1]]<>
" ",_,ToString[3 (n-1)]<>"-illion "]]
inWords[h_]:=If[h==0,"Zero",With[{n=numberform[h]},
StringJoin@@Table[createBlock[hundreds@n[[i]],Length[n]-i+1]
,{i,Length[n]}]]]
Here is the example Prashant gave...
In[55]:=
inWords[7317782180245641104170634561625559007936487060051082174021876603737988]
Out[55]= "Seven 69-illion Three Hundred Seventeen 66-illion Seven Hundred
Eighty Two Vigintillion One Hundred Eighty Novemdecillion Two Hundred
Forty Five Octodecillion Six Hundred Forty One Septendecillion One
Hundred Four Sexdecillion One Hundred Seventy Quindecillion Six
Hundred Thirty Four Quattuordecillion Five Hundred Sixty One
Tredecillion Six Hundred Twenty Five Duodecillion Five Hundred Fifty
Nine Undecillion Seven Decillion Nine Hundred Thirty Six Nonillion
Four Hundred Eighty Seven Octillion Sixty Septillion Fifty One
Sextillion Eighty Two Quintillion One Hundred Seventy Four
Quadrillion Twenty One Trillion Eight Hundred Seventy Six Billion Six
Hundred Three Million Seven Hundred Thirty Seven Thousand Nine
Hundred Eighty Eight"
Now to answer part 2 we need to work do the inverse of inWords
.
tonum[args___,last_]/;StringMatchQ[last,Alternatives@@big|"*illion"]:=
blockNum[last]*hundredNum[args]
tonum[args___,last_]:= hundredNum[args,last]
tonum[]:= 0
blockNum[arg:Alternatives@@big]:= 10^(3 Position[big,arg][[1,1]])
blockNum[bigNum_]:=
Power[10,Sequence@@ToExpression[StringCases[bigNum,DigitCharacter..]]]
oneNum[o_]:= Replace[o,Thread[Join[single,{_}]->Join[Range[1,9],{0}]]]
teenNum[]:= 0;
teenNum[o_]:= Replace[o,Thread[Join[teen,{_}]->Join[Range[10,19],{tenNum[o]}]]]
teenNum[t_,o_]:= tenNum[t,o]
tenNum[t_]:= Replace[t,Thread[Join[double,{_}]->
Join[Range[20,90,10],{oneNum[t]}]]]
tenNum[t_,o_]:= tenNum[t]+oneNum[o]
hundredNum[h_,"Hundred",t___]:= 100*oneNum[h]+teenNum[t]
hundredNum[h___]:= teenNum[h]
inNumbers[n_]:= Block[{temp=StringSplit[n],split,spans,parts},
split=Pick[Range[Length[temp]],
(MemberQ[big,#]||StringMatchQ[#,"*illion"])&/@temp
];
spans=Span@@@Transpose[{Join[{1},split+1],Join[split,{Length[temp]}]}];
parts=temp[[#]]&/@spans;
Total[tonum@@@parts]
]
So inNumbers
should be able to take a string version of the number and return the digits...
In[51]:= n =
7317782180245641104170634561625559007936487060051082174021876603737988;
In[52]:= inNumbers@inWords[n] == n
Out[52]= True
Speak
into text? If so that seems like something to try. (SpokenString
just returns the number) $\endgroup$ – Mike Honeychurch Jan 31 '12 at 22:06