这种逻辑编程实际上是在我的命令式编程技巧上跳舞。这是家庭作业,所以请不要给我答案。这就是我所拥有的:
fibo(N,1) :-
N < 2,
!.
fibo(N,R) :-
N1 is N-1,
N2 is N-2,
fibo(N1,R1),
fibo(N2,R2),
R is R1+R2.
我想要制作另一个看起来像这样的功能; fib(N,Value,LastValue)
。
N
是第n个数字,value是返回值。我不明白我怎么能用累积重写这个。而且由于它向后计数,我不知道它在计算任何东西之前如何“知道”最后一个值。 :s赞赏任何意见。
答案 0 :(得分:5)
我可以在这里发布解决方案,但既然这是家庭作业,那就会适得其反。相反,这是一个领导:
您列出的Fibonacci版本存在的问题是效率低下。每次调用fibo/2
都会导致另一个两个调用,但其中一些调用会计算相同斐波纳契数的值。例如,在伪代码中:
(a) fibo(4) -> fibo(3), fibo(2)
(b) fibo(3) -> fibo(2), fibo(1)
(c) fibo(2) -> fibo(1), fibo(0) % called from (a)
(d) fibo(2) -> fibo(1), fibo(0) % called from (b), redundant
为了克服这个缺陷,你被要求重新定义Fibonacci,不仅要返回最后一个值,还要返回最后两个值,这样每次调用fib/3
都只会导致一次递归调用(因此计算)斐波纳契线性时间序列)。您需要将基本案例更改为:
fib(1,1,0).
fib(2,1,1).
我会把递归案件留给你。
以下是递归案例:
fib(N, Val, Last) :-
N > 2,
N1 is N - 1,
fib(N1, Last, Last1), % single call with two output arguments,
% instead of two calls with one output argument
Val is Last + Last1.
答案 1 :(得分:2)
答案 2 :(得分:1)
也许使用尾递归是一个不错的选择
编辑: 你可以尝试像fib(6)= fib(6,0,0)这样的第一个参数就是步数,当它达到0时就停止了,而不是将fib(6)分解成fib(5)+ fib(4) ,第二个参数是你计算的最后一个值,第三个参数是要计算的值,它等于当前第二个和第三个参数的总和(第一步除外,其中0 + 0将为1)< / p>
所以计算你在每次调用时设置第二个参数并在第三个参数中累积,因此fib(6,0,0)=&gt; fib(5,0,1)=&gt; fib(4,1,1)=&gt; fib(3,1,2)=&gt; fib(2,2,3)=&gt; fib(1,3,5)=&gt; fib(0,5,8)然后你返回8
在该方法中,您实际上不必在堆栈中保存地址返回,从而避免堆栈溢出
答案 3 :(得分:0)
请记住,还有另一种计算斐波纳契数列的方法:从基础案例开始向上移动。
目前,要计算fib(n)
,您需要添加fib(n-1)
和fib(n-2)
。相反,根据Fibonacci序列的定义翻转并计算fib(0)
和fib(1)
,并从中进行构建。
答案 4 :(得分:-1)
你几乎已经拥有它了。只需改写:
fibo(N, Value) :-
N1 is N-1, N2 is N-2,
fibo(N1, LastValue),fibo(N2, SecondToLastValue),
Value is LastValue + SecondToLastValue.
fibo2(N, Value, LastValue):- ...
我不明白我怎么能改写 这使用积累
请注意,不需要这样做(尽管可以这样做)。