素数分解程序

时间:2015-04-02 16:40:13

标签: erlang

这是我的第一个Erlang计划。我的代码需要帮助。我刚刚得知我不能在守卫中调用函数,所以我试图在我的factor / 3辅助函数中使用“case”。代码编译,但我收到以下错误:

***异常错误:评估算术表达式时发生错误      在功能程序中:factor / 3(program.erl,第24行) *

  -module(program).
  -export([first/1, isProduct/1, factor/1]).


  %returns the first prime factor of the parameter(an integer greater than    1) passed to the function
  first(Num) -> first(Num, 2). 

  %private helper function for first(Num)
  first(Num, Count) when (Num rem Count) == 0 -> Count;
  first(Num, Count) -> Count = Count + 1,
  first(Num, Count).


  %returns the prime factorization of Num as a list of prime numbers
  factor(Num) -> factor(Num, Num, 1, [Rest, first(Num)])

  %helper function for factor(Num)
  factor(Num, StaticNum, Count, [First|Rest]) when Count == StaticNum -> [First, Rest];  
  factor(Num, StaticNum, Count, [First|Rest]) ->
  factor(Num div lists:last([Rest]), StaticNum, (Count * [Rest]), [Rest|first(Num div lists:last([Rest])])).

2 个答案:

答案 0 :(得分:2)

我修改了你的代码,因为你编写的版本无法编译。

这里有很多问题。

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,所以对于下一步,它应该是Num/Next,Next = first(Num)。请注意,在语法[First|Rest]中,First是一个元素(这里是一个整数),而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).

以下是使用timer测量的2个版本的结果:tc / 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]}

答案 1 :(得分:1)

我重写了你的代码,希望我理解你的任务。

-module(program).
-export([first/1]).

first(Num) when Num >1,is_integer(Num) ->{ok,factor(Num,2)};
first(Num)-> {err,Num}.

factor(Num,Count) when Count>Num+1->[];
factor(Num,Count)->case Num rem Count of
                     0->[Count|factor(Num div Count,Count)];
                     _->factor(Num,Count+1)
                   end.