在SICP中使用迭代过程的斐波纳契序列,无法完全理解

时间:2016-02-28 18:21:48

标签: loops scheme lisp fibonacci sicp

这是计算SICP中的斐波纳契序列的过程的迭代示例。这个想法是:

  • a = fib(n + 1)= a + b
  • b = fib(n)= a
(define (fib n) 
  (fib-iter 1 0 n))
(define (fib-iter a b count)
  (if (= count 0)
      b
      (fib-iter (+ a b) a (- count 1))))

更深入地看,我不明白为什么继续计算fib(n + 1)是必要的。我发现我们可以写了。

;; a and b are first and second integers respectively
;; in the recursive call, b would be replaced by a+b because it is the next number in the sequence
;; so now a will be replaced by the previous value of b because it is the previous value.
(define (fib2 n) 
  (fib-iter 1 0 n))
(define (fib-iter a b count)
  (if (= count 0)
      b
      (fib-iter b (+ a b) (- count 1))))

现在,我真的认为第一个例子,一个持续到n + 1的例子真的是多余的。我不明白为什么这是必要的。我提出的迭代示例有什么问题?

2 个答案:

答案 0 :(得分:1)

没有错。这两种方法给出了相同的结果。

#lang racket
(define (fib n) 
  (fib-iter 1 0 n))
(define (fib-iter a b count)
  (if (= count 0)
      b
      (fib-iter (+ a b) a (- count 1))))

(define (fib2 n) 
  (fib-iter2 1 0 n))

(define (fib-iter2 a b count)
  (if (= count 0)
      b
      (fib-iter2 b (+ a b) (- count 1))))

(define xs '(0 1 2 3 4 5 6 7 8 9 10))
(map fib  xs)
(map fib2 xs)

输出结果为:

'(0 1 1 2 3 5 8 13 21 34 55)
'(0 1 1 2 3 5 8 13 21 34 55)

这表明您确实在计算相同的序列。

答案 1 :(得分:1)

Bot程序产生正确的结果。但是,第一个保留ab之间的关系:aFib(i+1)bFib(i),其中i=n-count 。第二种方法使用第一次迭代来交换ab,从而引入一个冗余迭代。通过以下程序可以看出这一点:

> (define (fib n) 
  (fib-iter 1 0 n))

(define (fib-iter a b count)
  (if (= count 0)
      b
      (fib-iter (+ a b) a (- count 1))))
> (trace fib-iter)
> (fib 3)
>(fib-iter 1 0 3)
>(fib-iter 1 1 2)
>(fib-iter 2 1 1)
>(fib-iter 3 2 0)
<2
2
> (define (fib-iter a b count)
  (if (= count 0)
      b
      (fib-iter b (+ a b) (- count 1))))
> (trace fib-iter)
> (fib 3)
>(fib-iter 1 0 3)
>(fib-iter 0 1 2)
>(fib-iter 1 1 1)
>(fib-iter 1 2 0)
<2
2

你真正想要的是这样的:

> (define (fib n)
  (if (zero? n)
      0
      (fib-iter 0 1 (- n 1))))

(define (fib-iter a b count)
  (if (zero? count)
      b
      (fib-iter b (+ a b) (- count 1))))

> (trace fib-iter)
> (fib 3)
>(fib-iter 0 1 2)
>(fib-iter 1 1 1)
>(fib-iter 1 2 0)
<2
2

注意,迭代次数减少了一次。但是,我在程序fib中做了额外的工作。