Prolog代码计算阶乘

时间:2015-08-17 02:39:03

标签: prolog factorial

我是Prolog的新手,我正在尝试编写一段计算数字阶乘的代码。 这段代码工作正常:

fact(0,1).
fact(N, R) :- N > 0, N1 is N - 1, fact(N1, R1), R is R1 * N.

但是这个没有:

fact(0, 1).
fact(N, R) :- N > 0, fact(N - 1, R1), R is R1 * N.

有人可以解释一下吗?

2 个答案:

答案 0 :(得分:4)

问题是prolog主要使用统一来进行计算。要让它进行算术运算,您需要告诉它使用is运算符明确地执行此操作。

因此,在您的第一个程序中,您明确告诉它使用N1 is N - 1子句执行减法,以便按预期工作。

但是在你的第二个程序中,当你写fact(N - 1, R1)时,你不是要求算术计算,而是要求统一。

如果我定义了fact(5 - 1, foo).这个事实,那么我可以查询?- fact(N - 1, Y), write([N, Y]).,prolog会很高兴地将N5Y统一起来foo 1}}。此查询将输出[5, foo]

所以,更进一步,如果我有事实fact(foo - bar).,那么查询?- fact(X - Y), write([X, Y]).将很乐意统一并返回[foo, bar]-不表示减法 - 它是所表示事实结构的一部分。

答案 1 :(得分:2)

当传递算术表达式(而不是数字)时,您需要在某些时间评估表达式。

(>)/2之类的算术运算符会自动执行此操作,因此目标1 > (0+0)会成功,就像1 > 0一样。

隐式统一(在子句头中)和与(=)/2目标的明确统一表达了任意 Prolog术语的相等性,而不仅仅是算术表达式。所以目标0 = 0成功,但0 = (1-1)失败。

算术平等(=:=)/20 =:= 00 =:= (1-1)都成功。

fact/2的第二个定义中,您可以通过编写fact(N,1) :- N =:= 0.而不是fact(0,1).来使第一个子句更通用。作为额外的奖励,您可以运行?- fact(5+5,F).:)

之类的查询