【问题标题】:Prolog factorial predicateProlog阶乘谓词
【发布时间】:2017-02-22 00:01:05
【问题描述】:

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

例如,我可以拥有fact(3,F)fact(N,6)。 这是我的谓词,它有效,但我不太明白如何。我使用了trace,但仍然无法理解它。

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

【问题讨论】:

  • 你也可以手动“单步”遍历它:fact(3, F) 不匹配 fact(0, 1)(因为 3 和 0 不能统一),所以 Prolog 将匹配下一个子句 fact(N, F) 和 @ 987654331@。然后它再次调用fact(N1, F1) 并根据第一个子句提出N1 = 0F1 = 1,依此类推。注意,在找到解之后,它会尝试找到更多并且不会终止,导致堆栈溢出。
  • 我很好奇:如果你不知道它是如何工作的,你是怎么写这个谓词的?
  • @lurker:这很好理解:另一个版本可能会产生实例化错误。
  • @lurker:嗯,我是从这个版本开始的:factorial(0, 1). factorial(N, F):- N > 0, N1 is N - 1, factorial(N1, F1), F is N * F1.,一直尝试直到我明白为止。

标签: prolog factorial failure-slice


【解决方案1】:

您可以尝试逐步完成您的程序以了解发生了什么。你确实会很慢,而且很不可靠。或者,您改为让 Prolog 完成(部分)工作。所以想法是稍微修改一下程序,然后看看Prolog是怎么想的。

这是我在查看您的程序时看到的 - 这称为

事实(0,1):- false。
事实(N,F):-
        事实(N1,F1),N 是 N1 + 1,
        F 是 N * F1.

这个片段什么时候终止?看看剩下的可见部分! N 只在头脑中出现一次:没有人对第一个参数感兴趣! F 也一样。因此:无论您有什么参数,程序都不会终止。 因此您的原始程序也是如此!

在原始版本中不是很清楚。注意:

?- fact(29,F).
F = 8841761993739701954543616000000 

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

?- fact(29,1).
** LOOPS **

那么,如果不准确了解发生了什么,您如何才能找到这些问题呢?这就是 false 的用途。一个永远不真实的目标。如果您像 fact(29,F), <b>false</b>. 这样添加它,您将永远不会被漂亮的答案分心。

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

:- use_module(library(clpfd)).

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多