如何在列表中表示多个两个数字,例如123 * 12 = 1476
我想在这个例子中使用list来执行此操作它应该是这样的
mul([1,2,3],[1,2])
结果将为[1,4,7,6]
,而不会使用list_to_integer
函数将列表转换为数字。到目前为止我做到了这一点,但如果其中一个列表的长度等于一个
mul([],A) ->[];
mul(A,[]) ->[];
mul([H|T],B) ->
if
(length([H|T]) ==1) or (length(B)== 1)
->
[X*Y||X<-[H],Y<-B]++mul(T,B);
(length([H|T]) >1) or (length(B) > 1)
->
[X*Y||X<-[H],Y<-B]++mul(T,B)
end.
答案 0 :(得分:1)
例如,所以:
multi(List, N) when is_number(N) ->
element(1,
lists:foldr(
fun(X, {Sum, Index}) -> {Sum + X * N * pow10(Index), Index + 1} end,
{0, 0}, List));
multi(L1, L2) when is_list(L2) ->
List = [fun() -> multi(L1, X) end() || X <- L2],
element(1,
lists:foldr(
fun(X, {Sum, Index}) -> {Sum + X * pow10(Index), Index + 1} end,
{0, 0}, List)).
pow10(N) when N =:= 0 -> 1;
pow10(N) -> 10 * pow10(N - 1).
如果有一个foldr表达式相似的通知,则可以简化代码:
multi(List, N) when is_number(N) ->
element(1,
lists:foldr(
fun(X, {Sum, Index}) -> {Sum + X * N * pow10(Index), Index + 1} end,
{0, 0}, List));
multi(L1, L2) when is_list(L2) ->
multi([fun() -> multi(L1, X) end() || X <- L2], 1).
pow10(N) when N =:= 0 -> 1;
pow10(N) -> 10 * pow10(N - 1).
获取列表,请使用integer_to_list:
...
multi(L1, L2) when is_list(L2) ->
create_list(multi([fun() -> multi(L1, X) end() || X <- L2],1)).
create_list(Number)->
[X-48 || X<-integer_to_list(Number)].
...
答案 1 :(得分:1)
以下是不使用list_to_integer
或integer_to_list
的解决方案。算法称为long multiplication,通常在语言不支持big(大于INT.MAX)数的乘法/和时使用。以下是可以通过各种方式进行优化的基本实现,但在教育方面可以正常使用。
请记住 Erlang 支持长时间的乘法和开箱即用的长总和(而不是 C ),因此在现实生活中实现乘法是无用的应用。
sum(A, B) when is_list(A) andalso is_list(B) ->
lists:reverse(sum_impl(lists:reverse(A), lists:reverse(B), {[], 0})).
mult(A, B) when is_list(A) andalso is_list(B) ->
lists:reverse(mult_impl(lists:reverse(A), lists:reverse(B), {[], []})).
sum_impl([], [], {Res, 0}) -> Res;
sum_impl([], [], {Res, C}) -> sum_impl([C], [0], {Res, 0});
sum_impl(A, [], Acc) -> sum_impl(A, [0], Acc);
sum_impl([], B, Acc) -> sum_impl([0], B, Acc);
sum_impl([HA | TA], [HB | TB], {Res, C}) ->
sum_impl(TA, TB, {Res ++ [(HA + HB + C) rem 10], (HA + HB + C) div 10}).
mult_impl(_A, [], {Res, _C}) -> Res;
mult_impl(A, [HB | TB], {Res, C}) ->
mult_impl(A, TB, {sum_impl(Res, C ++ [X * HB || X <- A], {[], 0}), [0 | C]}).
答案 2 :(得分:0)
这是一个允许您指定基数(2-10)的版本:
在shell中:
167> c(my).
{ok,my}
168> Base10 = 10.
10
169> Base2 = 2.
2
170> my:list_mult([1,1], [1,1,1], Base10).
[1,2,2,1]
171> 11 * 111.
1221
172> my:list_mult([1,1], [1,1,1], Base2).
[1,0,1,0,1]
173> io:format("~.2B~n", [2#11 * 2#111]).
10101
ok
-module(my).
%%-compile(export_all).
-export([list_mult/3]).
-include_lib("eunit/include/eunit.hrl").
list_mult(List1, List2, Base) ->
Number = digits_to_int(List1, Base) * digits_to_int(List2, Base),
list_of_digits(Number, Base).
list_mult_test() ->
Base10 = 10,
?assertEqual(
list_of_digits(123 * 12, Base10),
list_mult([1,2,3], [1,2], Base10)
),
?assertEqual(
list_of_digits(2 * 5, Base10),
list_mult([2], [5], Base10)
),
?assertEqual(
list_of_digits(0 * 0, Base10),
list_mult([], [], Base10)
),
?assertEqual(
list_of_digits(0 * 23, Base10),
list_mult([], [2,3], Base10)
),
?assertEqual(
list_of_digits(30 * 4, Base10),
list_mult([0,3,0], [0,4], Base10)
),
?assertEqual(
list_of_digits(1 * 3, Base10),
list_mult([0,0,1], [0,3], Base10)
),
Base2 = 2,
?assertEqual(
list_of_digits(2#11 * 2#1000, Base2),
list_mult([1,1], [1,0,0,0], Base2)
),
?assertEqual(
list_of_digits(2#1001 * 2#10, Base2),
list_mult([1,0,0,1], [1,0], Base2)
),
%%Errors:
?assertThrow(
"illegal_number: Some elements are >= to Base",
list_mult([1,3], [1,0,0,0,0], Base2)
),
?assertThrow(
"illegal_number: Some elements are >= to Base",
list_mult([a, 3], [f,1], Base10) %%hex notation
).
%--------------
digits_to_int_test() ->
Base10 = 10,
?assertEqual(
123,
digits_to_int([1,2,3], Base10)
),
?assertEqual(
10,
digits_to_int([1,0], Base10)
),
?assertEqual(
3,
digits_to_int([3], Base10)
),
?assertEqual(
0,
digits_to_int([0], Base10)
),
?assertEqual(
0,
digits_to_int([], Base10)
),
Base2 = 2,
?assertEqual(
2#11,
digits_to_int([1,1], Base2)
),
?assertEqual(
2#1101,
digits_to_int([1,1,0,1], Base2)
),
?assertEqual(
2#11110000,
digits_to_int([1,1,1,1, 0,0,0,0], Base2)
),
?assertEqual(
2#1,
digits_to_int([1], Base2)
),
?assertEqual(
0,
digits_to_int([0], Base2)
),
?assertEqual(
0,
digits_to_int([], Base2)
),
%%Errors:
?assertThrow(
"illegal_number: Some elements are >= to Base",
digits_to_int([1,2,3], Base2)
),
?assertThrow(
"illegal_number: Some elements are >= to Base",
list_mult([a, 3], [f,1], Base10) %%hex notation
).
digits_to_int(List, Base) ->
HighestPower = length(List) - 1,
digits_to_int(List, Base, HighestPower, 0).
digits_to_int([], _, _, Sum) ->
Sum;
digits_to_int([X|Xs], Base, Power, Sum) when X<Base ->
Term = round( math:pow(Base, Power) * X ), %%round() converts float to integer.
digits_to_int(Xs, Base, Power-1, Sum+Term);
digits_to_int(_, _, _, _) ->
throw("illegal_number: Some elements are >= to Base").
%--------------
list_of_digits_test() ->
Base10 = 10,
?assertEqual(
[1,1],
list_of_digits(11, Base10)
),
?assertEqual(
[1,0,0],
list_of_digits(100, Base10)
),
?assertEqual(
[1],
list_of_digits(1, Base10)
),
?assertEqual(
[],
list_of_digits(0, Base10)
),
Base2 = 2,
?assertEqual(
[1,0,1,1],
list_of_digits(2#1011, Base2)
),
?assertEqual(
[1,1,1],
list_of_digits(2#111, Base2)
),
?assertEqual(
[1],
list_of_digits(1, Base2)
).
list_of_digits(0, _Base) ->
[];
list_of_digits(Number, Base) -> %% 193
HighestPower = get_highest_power(Number, Base),
list_of_digits(Number, Base, HighestPower, []).
list_of_digits(Number, _, 0, Digits) ->
lists:reverse([Number|Digits]);
list_of_digits(Number, Base, Power, Digits) ->
X = round(math:pow(Base, Power) ),
Digit = Number div X,
Remainder = Number rem X,
list_of_digits(Remainder, Base, Power-1, [Digit|Digits]).
%---------------
get_highest_power_test() ->
Base10 = 10,
?assertEqual(
2,
get_highest_power(199, Base10)
),
?assertEqual(
3,
get_highest_power(1999, Base10)
),
?assertEqual(
3,
get_highest_power(1000, Base10)
),
?assertEqual(
1,
get_highest_power(19, Base10)
),
?assertEqual(
0,
get_highest_power(5, Base10)
).
get_highest_power(Number, Base) ->
Power = 0,
KeepGoing = (Number div round(math:pow(Base,Power)) ) > 0,
get_highest_power(Number, Base, Power, KeepGoing).
get_highest_power(Number, Base, Power, KeepGoing) when KeepGoing =:= true ->
NewPower = Power+1,
StillKeepGoing = (Number div round(math:pow(Base, NewPower)) ) > 0,
get_highest_power(Number, Base, NewPower, StillKeepGoing);
get_highest_power(_, _, Power, KeepGoing) when KeepGoing =:= false ->
max(0, Power - 1).