4

我正在尝试使用以下函数计算斐波那契数列:

fib(0,A,_,A).
fib(N,A,B,F) :-
    N1 is N-1, Sum is A+B, fib(N1, B, Sum, F).
fib(N, F) :- fib(N, 0, 1, F).

这旨在像这样工作:

| ?- fib(20,Result).

Result = 6765 ? 

但是当我尝试这个时,它抱怨:

| ?- fib(What,6765).
uncaught exception: error(instantiation_error,(is)/2)

有谁明白为什么会这样?

4

3 回答 3

4

在第二条中:

fib(N,A,B,F) :-
    N1 is N-1, Sum is A+B, fib(N1, B, Sum, F).

N是一个要递减的变量,并且在您调用:

fib(What, 6765).

该变量尚未定义,因此您会在N1 is N - 1.

在 swipl 我什至得到了错误:

?- fib(W, 6765).
ERROR: fib/4: Arguments are not sufficiently instantiated
于 2012-12-24T13:00:36.773 回答
3

既然您知道这是一个错误,您介意知道它是否真的可以回答您的查询吗?

你会如何处理这个问题?你的功能没问题吧?确切地说,因为它是一个函数,而不是一个关系,所以你会得到错误。

解决它有点复杂,但 CLP 可以!

请参阅 CLP(FD)文档中的这个引人入胜的示例(在此处引用)

:- use_module(library(clpfd)).

n_factorial(0, 1).
n_factorial(N, F) :-
        N #> 0, N1 #= N - 1, F #= N * F1,
        n_factorial(N1, F1).

我们需要这样的东西,但对于斐波那契。看看它是多么容易:

:- [library(clpfd)].

fib(0,A,_,A).
fib(N,A,B,F) :-
    N #> 0,
    N1 #= N-1,
    Sum #= A+B,
    fib(N1, B, Sum, F).
fib(N, F) :- fib(N, 0, 1, F).

即用is/2替换/ #=2,我们得到

?- fib(20,Result).
Result = 6765 .

?- fib(X,6765).
X = 20 ;
^C

注意,在第一次响应后程序循环!你有办法纠正它吗?或者另一个问题可能值得......

于 2012-12-24T17:30:51.510 回答
0

更清晰、更自然的谓词定义可能是:

//The two base steps
fib1(0,0). 
fib1(1,1).
//the recursive step
fib1(N,F) :- 
        N >= 0, M is N-2, O is N-1, fib1(M,A), fib1(O,B), F is A+B.

它也是一个只有一个谓词的定义:fib/2

于 2013-04-10T20:08:02.740 回答