0

这是我的谓词,它应该检查斐波那N数是否是NthFib

我得到算术不是函数错误。

K - current iteration
N - Nth number
Tmp - previous Fibonacci number
Ans - current Fibonacci number

斐波那契数列:1、1、2、3、5、8、13、21 等(前两个之和 = 当前)

fib(N, NthFib) :-
    fib(1, N, 1, 0, NthFib).

fib(K, N, Ans, Tmp, NthFib) :-
    % true if Ans is NthFib, false otherwise
    ( K > N -> Ans is NthFib
    ; K =< N -> fib( K + 1, N, Ans + Tmp, Ans, NthFib)
    ).
4

3 回答 3

2

首先,将您的原始代码重写为

fib(N, NthFib) :- fib(1, N, 1, 0, NthFib).

fib(K, N, Ans, Tmp, NthFib) :- 
  K > N -> Ans = NthFib;       % use = instead of is here
  K =< N -> fib((K+1), N, (Ans+Tmp), Ans, NthFib).

现在,

?- fib(7,X).

X = 1+0+1+ (1+0)+ (1+0+1)+ (1+0+1+ (1+0))+ (1+0+1+ (1+0)+ (1+0+1))+ 
       (1+0+1+ (1+0)+ (1+0+1)+ (1+0+1+ (1+0))) 

Yes
?- fib(7,X), Z is X.

X = 1+0+1+ (1+0)+ (1+0+1)+ (1+0+1+ (1+0))+ (1+0+1+ (1+0)+ (1+0+1))+ 
       (1+0+1+ (1+0)+ (1+0+1)+ (1+0+1+ (1+0)))
Z = 21 

看,在 Prolog 中数据是符号的,并且 usingis将算术表达式强制转换为算术值(在假设它是有意义的算术表达式的情况下评估表达式)。

要检查 20 是否是第 7 个斐波那契数,我们可以使用算术比较运算符来评估其参数,

?- fib(7,X), X =:= 20.

No

这意味着您的代码只需要重写为

fib(N, NthFib) :- fib(1, N, 1, 0, NthFib).

fib(K, N, Ans, Tmp, NthFib) :- 
  K > N -> NthFib is Ans ;       % exchange the order of operands
  K =< N -> fib((K+1), N, (Ans+Tmp), Ans, NthFib).

现在它可以按您的预期工作:

?- fib(7,21).

Yes
?- fib(7,20).

No

但它不能有效地工作,将所有这些长表达式作为符号数据携带。我们只需要真正的数字,所以正如您在其他答案中显示的那样,is用于实现这一目标。您拥有的每个符号子表达式,将其从其封闭表达式中取出,并命名它,使用is而不是=.

BTW 21 确实是该序列的第 8 个成员。更正您的代码。

于 2012-05-25T07:37:18.490 回答
1

如果K是统一的1K + 1是统一的1 + 1,不是2的。

于 2012-05-20T22:28:41.987 回答
-1

我重写了一个算法,现在更简单高效:

fib(0, 0).
fib(1, 1).
fib(N, F) :-
    N > 0,
    X is N - 2,
    Y is N - 1,
    fib(X, A),
    fib(Y, B),
    F is A + B.
于 2012-05-21T10:29:50.303 回答