Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops fibonacci序列在SICP中使用迭代过程,不能完全理解_Loops_Scheme_Lisp_Fibonacci_Sicp - Fatal编程技术网

Loops fibonacci序列在SICP中使用迭代过程,不能完全理解

Loops fibonacci序列在SICP中使用迭代过程,不能完全理解,loops,scheme,lisp,fibonacci,sicp,Loops,Scheme,Lisp,Fibonacci,Sicp,这里是计算SICP中斐波那契序列的迭代示例。这个想法是: a=fib(n+1)=a+b b=fib(n)=a 更深入地看,我不明白为什么继续计算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 sequenc

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

  • a=fib(n+1)=a+b
  • b=fib(n)=a
更深入地看,我不明白为什么继续计算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的例子是多余的。我不明白为什么这是必要的。我提出的迭代示例有什么问题吗?

没有什么问题。这两种方法给出了相同的结果

#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)

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

Bot过程产生正确的结果。然而,第一种方法保留了
a
b
之间的关系:
a
Fib(i+1)
b
Fib(i)
其中
i=n-count
。第二种方法使用第一次迭代交换
a
b
,从而引入一次冗余迭代。这可以通过跟踪程序来看出:

> (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
>(定义(fib n)
(国际热核聚变实验堆1 0 n))
(定义(光纤a b计数)
(如果(=计数0)
B
(光纤(+AB)a(-计数1)))
>(微量纤维测试仪)
>(fib 3)
>(国际热核实验堆1 0 3)
>(国际热核实验堆1-2)
>(国际热核实验堆2 1)
>(国际热核实验堆3 2 0)
(定义(光纤a b计数)
(如果(=计数0)
B
(纤维b(+AB)(计数1)))
>(微量纤维测试仪)
>(fib 3)
>(国际热核实验堆1 0 3)
>(fib iter 0 1 2)
>(国际热核实验堆1)
>(fib iter 1 2 0)
(定义(fib n)
(如果(零?n)
0
(fib iter 0 1(-n 1)))
(定义(光纤a b计数)
(如果(零?计数)
B
(纤维b(+AB)(计数1)))
>(微量纤维测试仪)
>(fib 3)
>(fib iter 0 1 2)
>(国际热核实验堆1)
>(fib iter 1 2 0)

这实际上只是解决完全相同问题的两种等效方法。我不认为第一个版本在任何方面都是“多余的”:它所做的工作量与第二个版本完全相同。这里的区别是微不足道的——我不会读懂它,也不会为此而激动。我认为您的主要困惑可能只是因为原始版本使用
a
作为较大的数字,
b
作为较小的数字,这是违反直觉的,而您的第二个实现颠倒了顺序(这恰好是由于算法的工作原理)。事实上,第一个版本确实计算了一个“额外”成员,即第(n+1)个成员;但是,第二个也有一个额外的成员(-1)-th 1.:)提前第一次停止会使代码复杂化-通常以
a
参数作为结果,对于第0个成员,我们必须以
b
作为结果。
fib-iter2
应该调用自身,而不是
fib-iter
。然后这两个过程真的计算相同的序列。你是对的!当我重新命名时,我遗漏了一个标识符。我更新了答案。“a是Fib(I+1),b是Fib(I)”-我明白了。但他们为什么要保留这种关系呢?我认为递归过程有这种关系,尽管我还看不到它。@morbidCode他们没有。如果相同的属性贯穿始终,那么它只是有助于对过程和正确性进行推理。您的第二个版本需要一次迭代来交换此关系中的
a
b
:实际上这是个不错的主意(类似于欧几里德
GCD(m,n)
算法当
mso这段代码中的课程是试图保留代码的属性,以便更好地进行推理?这个属性与不变量相同吗?保留变量关系有多重要?我在问,因为如果我试图为fibonacci创建一个只熟悉递归过程的迭代过程,我不知道ink我会想出一个与书中相同的解决方案。@morbidCode是的,这是不变的。我想你会想出类似的解决方案:你只需要找到保持最后两个值的方法。顺便说一句,SICP有一个基于Ch3中的流的解决方案,它更优雅。那么a=1=fib(n+1)如何呢在迭代过程中。这对我来说不是很明显,但我认为这两个过程中的关系都应该成立,对吗?我现在能想到的唯一原因是:在递归过程中,fib(n)对于序列中的下一个数字总是fib(n-1)。因为在迭代过程中a=a+b,b=a,b将是fib(n),a(fib(n-1))+b=fib(n+1)!
> (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