Я изменил ваш код, потому что написанная вами версия не может скомпилироваться.
Здесь много проблем.
first(Num, Count) ->
Count = Count + 1,
first(Num, Count).
Переменные не изменяемые! Вы не можете сделать это, но вы можете вспомнить первый/2 с новыми параметрами:
first(Num, Count) ->
first(Num, Count+1).
Кроме того, эта функция никогда не остановится, если он вызывается с параметром 1. Вам необходимо добавить результат для этого.
%returns the product of factors-in-a-list.
isProduct([]) -> 0;
isProduct([First|Rest]) -> First * isProduct(Rest).
Эта функция всегда возвращает 0, так как она всегда заканчивается обнаружением пустого списка. Вы должны написать isProduct([]) -> 1;
Когда вы находите последний фактор вы вставить его в списке с плохим синтаксисом: использовать [First|Rest];
не [First, Rest];
, когда вы хотите перебрать, первый параметром является текущим остальным Числа, поэтому для следующим шагом должно быть Num/Next
с Next = first (Num). Обратите внимание, что в синтаксисе [First|Rest]
Сначала это элемент (здесь целое число), а Rest - это список, и вы не можете использовать список для арифметической операции.
Последнее, что вы хотите добавить новый элемент в список простых чисел, это будет Next = first(Num)
, и вы должны положить его в начало списка и продолжить с Num div Next
(это относится к первому вызову factor/3)
ваш код становится:
-module(program).
-export([factor/1]).
%returns the first prime factor of the parameter(an integer greater than 1) passed to the function
first(1) -> 1;
first(Num) -> first(Num, 2).
%private helper function for first(Num)
first(Num, Count) when (Num rem Count) == 0 -> Count;
first(Num, Count) -> first(Num, Count+1).
%returns the product of factors-in-a-list.
isProduct([]) -> 1;
isProduct([First|Rest]) -> First * isProduct(Rest).
%returns the prime factorization of Num as a list of prime numbers
factor(Num) when is_integer(Num), Num > 0 ->
First = first(Num),
factor(Num div First, Num,[First]).
%helper function for factor(Num)
factor(Num, StaticNum, [First|Rest]) ->
case isProduct([First|Rest]) == StaticNum of
true -> [First|Rest];
false ->
Next = first(Num),
factor(Num div Next, StaticNum, [Next,First|Rest])
end.
вашей версия не оптимизирована, так как перезапуск первого в 2 каждый раз (важно, когда есть много простых множителей) и условие остановки не оптимизировано (важно, когда есть некоторые «большие» основные факторы). Я бы написать так:
decomp(N) when is_integer(N), (N > 0) ->
lists:reverse(decomp(N,[],2)).
decomp(N,R,I) when I*I > N -> [N|R];
decomp(N,R,I) when (N rem I) =:= 0 -> decomp(N div I,[I|R],I);
decomp(N,R,2) -> decomp(N,R,3);
decomp(N,R,I) -> decomp(N,R,I+2).
Вот результат для 2-й версий, измеренных с таймером: дц/3 (на Windows 7), разность времени выполнения огромна, более чем 15000 раз быстрее, для этого Пример:
2> timer:tc(program,factor,[1234567893200]).
{91349000,[3086419733,5,5,2,2,2,2]}
3> timer:tc(program,decomp,[1234567893200]).
{6000,[2,2,2,2,5,5,3086419733]}
На последней строке вы пытаетесь разделить число на список: 'Num/[Rest]', что почти наверняка является источником вашей ошибки, поскольку это невозможно. Что вы на самом деле пытаетесь сделать там? Вам нужно переосмыслить свой подход и изменить свой код. Также обратите внимание, что вы скорее всего хотите использовать 'div', а не'/', потому что вы пытаетесь сделать целочисленное деление. –
В конце списка есть элемент, который я хочу разделить. Как я могу это сделать. –
'Rest' - это хвост списка, поэтому он может быть пустым. –