English 中文(简体)
How to convert numbers to words in Erlang?
原标题:

I found this interesting question about converting numbers into "words":

Code Golf: Number to Words

I would really like to see how you would implement this efficiently in Erlang.

最佳回答
-module(int2txt).
-export([convert/1]).

convert(0) -> "zero";
convert(N) -> convert1(N).

convert1(0) -> "";
convert1(N) when N>=1000 ->
    join(convert_thou(thoubit(N), 0),convert1(N rem 1000));
convert1(N) when N>=100 ->
    join(convert1(N div 100),"hundred",convert1(N rem 100));
convert1(N) when N>=20 ->
    join(tens((N div 10)-1) ++"ty",convert1(N rem 10));
convert1(N) when N>=13 -> teens(N-12) ++ "teen";
convert1(N) -> ones(N).

convert_thou({0,0},_) -> "";
convert_thou({0,N2},C) -> convert_thou(thoubit(N2),C+1);
convert_thou({N,N2},C) -> join(convert_thou(thoubit(N2),C+1),
                   convert1(N),thouword(C)).

thoubit(N) -> {(N div 1000) rem 1000,N div 1000}.

ones(N) -> element(N,{"one","two","three","four","five","six","seven",
              "eight","nine","ten","eleven","twelve"}).
tens(N) -> element(N,{"twen","thir","for","fif","six","seven","eigh","nine"}).
teens(2) -> "four";
teens(N) -> tens(N+1).
thouword(0) -> "thousand";
thouword(C) -> illions(C) ++ "illion".
illions(N) -> element(N,{"m","b","tr","quadr","quint","sex","sept",
                         "oct","non","dec"}).

join(X,Y,Z) -> join(join(X,Y),Z).
join("",X) -> X;
join(X,"") -> X;
join(X,Y) -> X++" "++Y.

Tests:

1> int2txt:convert(0).
"zero"
2> int2txt:convert(1024).
"one thousand twenty four"
3> int2txt:convert(1048576).
"one million forty eight thousand five hundred seventy six"
4> int2txt:convert(1073741824).
"one billion seventy three million seven hundred forty one thousand
eight hundred twenty four"
5> int2txt:convert(1000001).   
"one million one"
问题回答
int2text(Num) when is_integer(Num) -> int2text(integer_to_list(Num));
int2text(Num) ->
  Segs = segment(0, lists:reverse(Num)),
  Words = lists:reverse([Seg || Seg <- Segs, Seg =/= []]),
  string:join(Words, " ").

segment(Ths, "")          -> segment3(Ths, [$0,$0,$0]);
segment(Ths, [A])         -> segment3(Ths, [$0,$0,A]);
segment(Ths, [A,B])       -> segment3(Ths, [$0,B,A]);
segment(Ths, [A,B,C|Num]) -> segment3(Ths, [C,B,A]) ++ segment(Ths+1, Num).

segment3(_Ths, [$0,$0,$0]) -> [];
segment3(Ths,  [$0,A,B])   -> [thousands(Ths)] ++ segment2([A,B]);
segment3(Ths,  [A,B,C])    -> [thousands(Ths)] ++ segment2([B,C]) ++ ["hundred", ones([A])].

segment2([$0,A]) -> [ones([A])];
segment2([$1,A]) -> [ones([$1,A])];
segment2([A,B])  -> [ones([B]), tens([A])].

ones("0") -> "";
ones("1") -> "one";
...
ones("18") -> "eighteen";
ones("19") -> "nineteen".

tens("2") -> "twenty";
...
tens("9") -> "ninety".

thousands(0) -> "";
thousands(1) -> "thousand";
thousands(2) -> "million";
...
-module(num2word).
-export([num2word/1]).

num2word(0) ->
    "Zero";
num2word(N) when N < 10 ->
    lists:nth(N, ["One",   "Two", "Three", "Four", "Five",
                  "Six", "Seven", "Eight", "Nine"]);
num2word(N) when N < 20 ->
    lists:nth(N-9, [     "Ten",    "Eleven",   "Twelve",
                    "Thirteen",  "Fourteen",  "Fifteen",
                     "Sixteen", "Seventeen", "Eighteen",
                    "Nineteen"]);
num2word(N) when (N < 100) and ((N rem 10) =:= 0) ->
    lists:nth((N div 10)-1, ["Twenty",  "Thirty",  "Forty",  "Fifty",
                              "Sixty", "Seventy", "Eighty", "Ninety"]);
num2word(N) when N < 100 ->
    num2word((N div 10) * 10) ++ " " ++ num2word(N rem 10);
num2word(N) when ((N rem 100) =:= 0) ->
    {Scale, Name} = scale(N),
    Result = num2word(N div Scale) ++ " " ++ Name,
    case (N rem Scale) of
        0 -> Result;
        Remainder -> Result ++ " " ++ num2word(Remainder)
    end;
num2word(N) ->
    {Scale, _} = scale(N),
    num2word((N div Scale) * Scale) ++ " " ++ num2word(N rem Scale).

scale(N) when N < 1000 ->
    {100, "Hundred"};
scale(N) when N < 1000000 ->
    {1000, "Thousand"};
scale(N) when N < 1000000000 ->
    {1000000, "Million"};
scale(N) when N < 1000000000000 ->
    {1000000000, "Billion"};
scale(N) when N < 1000000000000000 ->
    {1000000000000, "Trillion"};
scale(N) when N < 1000000000000000000 ->
    {1000000000000000, "Quadrillion"};
scale(N) when N < 1000000000000000000000 ->
    {1000000000000000000, "Quintillion"}.




相关问题
Colorize negative/positive numbers (jQuery)

I d like to color numbers in a table for better readability:  green for positive (+00.00); red for negative (-00.00) and; black for default case (no sign)

Limit the # of rows being housed in a SQL table

This is a table design issue. I have a table that stores IP addresses. The data in the table is queried very heavily. The IPs can have different flags such as "unblocked", "temporarily blocked" and ...

Check if string contains only digits

I want to check if a string contains only digits. I used this: var isANumber = isNaN(theValue) === false; if (isANumber){ .. } But realized that it also allows + and -. Basically, I want to make ...

How to convert numbers to words in Erlang?

I found this interesting question about converting numbers into "words": Code Golf: Number to Words I would really like to see how you would implement this efficiently in Erlang.

热门标签