【发布时间】:2020-01-23 20:07:05
【问题描述】:
SICP 练习 3.57:当我们使用
fibs的定义计算 nth 斐波那契数时,执行了多少次加法运算add-streams程序?表明如果我们将(delay ⟨exp⟩)简单地实现为(lambda () ⟨exp⟩),而不使用3.5.1 中描述的memo-proc过程提供的优化,则添加的数量将成倍增加。
网上有很多解决方案。大多数人声称fib 序列的非优化memo-proc 序列版本与计算非记忆常规fib 函数相同。在跟踪未优化的 memo-proc 版本的添加时,我看到了不同的情况。
令 A(n) 为对 (stream-ref fibs n) 执行的加法次数
- A(0) = 0
- A(1) = 0
- A(2) = 1
- A(3) = 3
- A(4) = 7
- A(5) = 14
- A(6) = 26
当在非优化(非记忆流)上使用替换和函数定义时,我可以确切地看到这些添加是什么以及它们发生的原因,但我无法想出一个好的方程来回答这个问题它实际上是指数级的。
例如,为 A(4) 追踪的添加是:
- 1 + 0
- 1 + 0
- 1 + 1
- 1 + 0
- 1 + 1
- 1 + 0
- 2 + 1
这里有一些伪代码来显示(stream-ref fibs 4) 的替换,其中“.”代表中缀stream-cons,{e} 代表承诺执行e。
(cddddr fibs)
(cddr (add-streams (cdr fibs) fibs))
(cddr (stream-map + (cdr fibs) fibs)))
(cddr ((+ 1 0) . {stream-map + (cddr fibs) (cdr fibs)}))
(cdr (stream-map + (cddr fibs) (cdr fibs)))
(cdr (stream-map + ((+ 1 0) . {stream-map + (cddr fibs (cdr fibs)}) (cdr fibs))
(cdr (+ 1 1) . {stream-map + (stream-map + (cddr fibs) (cdr fibs)) (cddr fibs)})
(stream-map + (stream-map + (cddr fibs) (cdr fibs)) (cddr fibs))
(stream-map + (stream-map + ((+ 1 0) . {stream-map + (cddr fibs) (cdr fibs)}) (cdr fibs)) (cddr fibs)
(stream-map + (stream-map + ((+ 1 0) . {stream-map + (cddr fibs) (cdr fibs)}) (1 . {stream-map + (cdr fibs) fibs)})) (cddr fibs))
(stream-map + ((+ 1 1) . {stream-map + (stream-map + (cddr fibs) (cdr fibs)) (stream-map + (cdr fibs) fibs)}) ((+ 1 0) . {stream-map + (cddr fibs) (cdr fibs)})
(+ 2 1) . {stream-map + (stream-map + (stream-map + (cddr fibs) (cdr fibs)) (stream-map + (cdr fibs) fibs))) (stream-map + (cddr fibs) (cdr fibs))}
这是实际的球拍代码:
#lang racket
(define-syntax-rule (delay f) (lambda () f))
(define (force f) (f))
(define stream-null? null?)
(define the-empty-stream '())
(define-syntax-rule (cons-stream a b)
(cons a (delay b)))
(define stream-car car)
(define (stream-cdr stream) (force (cdr stream)))
(define (add-streams s1 s2)
(define (add x y)
(begin
(display "Adding ")
(display x)
(display " + ")
(display y)
(newline)
(+ x y)))
(stream-map add s1 s2))
(define (stream-map proc . argstreams)
(if (stream-null? (car argstreams))
the-empty-stream
(cons-stream
(apply proc (map stream-car argstreams))
(apply stream-map
(cons proc
(map stream-cdr
argstreams))))))
(define (stream-ref s n)
(if (= n 0)
(stream-car s)
(stream-ref (stream-cdr s) (- n 1))))
(define fibs
(cons-stream
0 (cons-stream
1 (add-streams
(stream-cdr fibs) fibs))))
(stream-ref fibs 4)
网上的大多数答案都是a(n) = a(n - 1) + a(n - 2) + 1。
跟踪的输出讲述了一个不同的故事。
【问题讨论】:
标签: scheme racket fibonacci sicp lazy-sequences