Prolog阶乘谓词

Prolog阶乘谓词,prolog,factorial,failure-slice,Prolog,Factorial,Failure Slice,我有一个阶乘谓词fact(N,F),其中N或F或两者都有界于一个数字 例如,我可以有事实(3,F)或事实(N,6)。 这是我的谓词,它起作用了,但我真的不明白它是如何起作用的。我使用了跟踪,但仍然无法理解它 fact(0,1). fact(N,F) :- fact(N1,F1), N is N1 + 1, F is N * F1. 你可以试着一步一步地完成你的计划,以了解发生了什么。你真的会很慢,而且很不可靠。或者,您让Prolog做(部分)工作

我有一个阶乘谓词
fact(N,F)
,其中
N
F
或两者都有界于一个数字

例如,我可以有
事实(3,F)
事实(N,6)
。 这是我的谓词,它起作用了,但我真的不明白它是如何起作用的。我使用了
跟踪
,但仍然无法理解它

fact(0,1).
fact(N,F) :-
        fact(N1,F1),
        N is N1 + 1,
        F is N * F1.

你可以试着一步一步地完成你的计划,以了解发生了什么。你真的会很慢,而且很不可靠。或者,您让Prolog做(部分)工作。所以我们的想法是稍微修改一下程序,然后看看Prolog对它的看法

这就是我在看你们的程序时看到的——这叫做

起初这看起来不错,但是如果你问下一个答案(用空格或
),你会以循环结束。更糟糕的是,错误查询现在会立即循环:

?- fact(29,1).
** LOOPS **
那么,在不确切了解情况的情况下,你如何发现这些问题呢?这就是错误的原因。一个永远不会实现的目标。如果你像
fact(29,F),false那样添加它。
你永远不会被漂亮的答案分心

你为什么把所有的算术都放在最后?我怀疑是因为你以前犯过一些错误。有一种简单的方法可以避免所有此类错误:

:- use_module(library(clpfd)).

你现在写的不是
,而是
,你需要一些限制,比如
N>=1
。我可以把您留在那里吗?

您也可以手动“逐步”完成它:
事实(3,F)
事实(0,1)
不匹配(因为3和0不可统一),所以Prolog将下一个子句
事实(N,F)
N=3匹配。然后,它再次调用
fact(N1,F1)
并根据第一个子句生成
N1=0
F1=1
,依此类推。请注意,在找到解决方案后,它会尝试查找更多内容,但不会终止,从而导致堆栈溢出。我很好奇:如果您不知道它是如何工作的,您是如何编写此谓词的?@潜伏者:这很容易理解:另一个版本可能产生了实例化错误。@潜伏者:嗯,我从这个版本开始:
factorial(0,1)。阶乘(N,F):-N>0,N1是N-1,阶乘(N1,F1),F是N*F1。
,并一直尝试,直到我得到它。
?- fact(29,1).
** LOOPS **
:- use_module(library(clpfd)).