【问题标题】:Prolog code calculating factorialProlog代码计算阶乘
【发布时间】:2015-08-18 17:51:07
【问题描述】:

我是 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.

谁能解释一下?

【问题讨论】:

  • 可以重写fact\2 的第二个版本,每次都评估它的第一个参数,并在第二个版本中解决这个问题,但更传统的做法是在第一个版本中做(通过前评估)。 Prolog 管理参数“惰性求值”的灵活性可能很有用,但阶乘计算过于简单,无法利用它。
  • 一个挑战是将任一版本重写为尾递归(符合最后调用优化的条件)。通常需要引入一个额外的参数(例如fact/3)来完成这项工作。

标签: prolog factorial


【解决方案1】:

问题在于 prolog 主要使用 unification 来进行计算。要让它进行算术运算,您需要使用 is 运算符明确地告诉它这样做。

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

但是在你写fact(N - 1, R1)的时候,你不是要求算术计算,而是要求统一。

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

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

【讨论】:

    【解决方案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). 的查询:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-26
      • 2018-10-06
      • 2018-03-27
      • 2022-01-17
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      相关资源
      最近更新 更多