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)).