首先,将您的原始代码重写为
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 个成员。更正您的代码。