Prolog阶乘递归

Cyb*_*hot 11 recursion prolog factorial

我无法理解以下因子程序

fact1(0,Result) :-
    Result is 1.
fact1(N,Result) :-
    N > 0,
    N1 is N-1,
    fact1(N1,Result1),
    Result is Result1*N.
Run Code Online (Sandbox Code Playgroud)

什么时候fact1被称为嵌套在第二行fact1,这是不是意味着最后一行,Result is Result1*N.永远不会被调用?或者在Prolog中,最后一行是在递归调用之前执行的吗?

m09*_*m09 12

BTW一旦你理解了基本的递归,尽可能尝试实现尾递归,这里它是:

factorial(N, R) :- factorial(N, 1, R).
factorial(0, R, R) :- !.
factorial(N, Acc, R) :-
    NewN is N - 1,
    NewAcc is Acc * N,
    factorial(NewN, NewAcc, R).
Run Code Online (Sandbox Code Playgroud)

与先前使用的递归不同,尾递归允许解释器/编译器在进行下一步递归时刷新上下文.所以,假设您计算factorial(1000),您的版本将保持1000个上下文,而我的版本将仅维持1.这意味着您的版本最终将无法计算所需的结果,但只会出现Out of call stack memory错误.

您可以在维基百科上阅读更多相关信息.

  • 目标`factorial(0,0)`*应该*失败 - 它不会. (2认同)

小智 7

一个相当简单的方法是:

fac(0,1).
fac(N,F):-
    N>0,N1 is N-1,fac(N1,F1),F is N*F1.
Run Code Online (Sandbox Code Playgroud)

  • 这个答案被标记为(不是答案)低质量队列.完全由代码组成的答案通常被忽视,因为它们为未来的读者提供了很少的背景/帮助.目前,除非您添加更多细节,否则可能会删除此答案. (2认同)
  • 你能否[编辑]你的答案,解释为什么这段代码能回答这个问题?仅限代码的答案[不鼓励](http://meta.stackexchange.com/questions/148272),因为他们没有教授解决方案. (2认同)

Car*_*rum 6

不,递归调用首先发生!它必须,或者最后一个条款毫无意义.算法分解为:

factorial(0) => 1
factorial(n) => factorial(n-1) * n;
Run Code Online (Sandbox Code Playgroud)

如您所见,您需要在乘法之前计算递归的结果,以便返回正确的值!

您的prolog实现可能有一种方法来启用跟踪,这将让您看到整个算法运行.这可能会帮助你.

  • 追踪总是有帮助的! (3认同)
  • 我希望你的意思是`factorial(0)=> 1` :) (3认同)
  • 怎么样`factorial(-1)`?根据上面的定义,查询"? - fact1(-1,_)."正确失败; `factorial`,实际上不是. (2认同)

rep*_*eat 5

一般来说,@ m09的答案基本上是关于尾递归的重要性.

对于大 N,计算产品不同赢!想想"二叉树",而不是"线性列表"......

让我们尝试两种方式并比较运行时间.首先,@ m09factorial/2:

?- time((factorial(100000,_),false)).
% 200,004 inferences, 1.606 CPU in 1.606 seconds (100% CPU, 124513 Lips)
false.

接下来,我们使用 reduce/3lambda表达式来树形式:

?- time((numlist(1,100000,Xs),reduce(\X^Y^XY^(XY is X*Y),Xs,_),false)).
% 1,300,042 inferences, 0.264 CPU in 0.264 seconds (100% CPU, 4922402 Lips)
false.

最后,让我们定义并使用专用的辅助谓词 x_y_product/3:

x_y_product(X, Y, XY) :- XY is X*Y.
Run Code Online (Sandbox Code Playgroud)

有什么好处?我们问秒表吧!

?- time((numlist(1,100000,Xs),reduce(x_y_product,Xs,_),false)).
% 500,050 inferences, 0.094 CPU in 0.094 seconds (100% CPU, 5325635 Lips)
false.