2011-02-23 56 views
2

考虑以下两个略有不同的方法用于计算第五根:为什么这些略有不同的寻根方法会产生不同的结果?

(define (fifth-root-right x) 
    (fixed-point-of-transform (lambda (y) (/ x (expt y 4))) 
          (repeated average-damp 2) 
          1.0)) 

(define (fifth-root-wrong x) 
    (fixed-point (repeated 
       (average-damp (lambda (y) (/ x (expt y 4)))) 
       2) 
       1.0)) 

都试图计算第五根平均衰减搜索一个固定点,因为x的第五根是地图y的固定点 - > x /(y^4)。我定义

(define (average-damp f) 
    (lambda (x) (average x (f x)))) 
(define tolerance 0.00001) 
(define (fixed-point f first-guess) 
    (define (close-enough? v1 v2) 
    (< (abs (- v1 v2)) tolerance)) 
    (define (try guess) 
    (let ((next (f guess))) 
     (if (close-enough? guess next) 
      next 
      (try next)))) 
    (try first-guess)) 
(define (fixed-point-of-transform g transform guess) 
    (fixed-point (transform g) guess)) 
(define (repeated f n) 
    (if (= n 1) 
     f 
     (compose f (repeated f (- n 1))))) 
(define (compose f g) (lambda (x) (f (g x)))) 

尝试这两种方法,我们得到

> (fifth-root-right 32) 
2.000001512995761 
> (fifth-root-wrong 32) 
2.8804315666156364 

为什么第二种方法给不能正确计算第五根源是什么?更奇怪的是,如果我们试图在第四或第三根这种错误的方法,它工作正常:

(define (fourth-root x) 
    (fixed-point (repeated 
       (average-damp (lambda (y) (/ x (expt y 3)))) 
       2) 
       1.0)) 

(define (cube-root x) 
    (fixed-point (repeated 
       (average-damp (lambda (y) (/ x (expt y 2)))) 
       2) 
       1.0)) 


> (fourth-root 16) 
1.982985155172348 
> (cube-root 8) 
2.0000009087630515 

以供参考,该代码试图解决计算机程序的Exercise 1.45结构和解释。现在我有正确的方法,我的代码有效,但我不明白为什么我的错误方法是错误的。

+0

你的第三和第四度例子似乎是正确方式的副本,而不是错误的方式。 – btilly 2011-02-23 02:26:37

+0

谢谢,现在固定正确和错误的标签。 – petehern 2011-02-23 15:25:14

回答

3

本质区别在于什么功能重复两次。在正确的一个,average-damp正在申请两次,净效应更多的阻尼; ((repeated average-damp 2) f)在数学上减少为(lambda (x) (+ (* 0.75 x) (* 0.25 (f x))))(道歉,如果我的语法关闭,我的lisp非常非常生锈)。这使得该算法不易受到变换的疯狂波动的影响。

第二个,不过,适用(average-damp (lambda (y) (/ x (expt y 2))))两次 - 即,它衰减所述变换一次,然后重复所得到的函数。 average-damp的一个应用程序恰好足以使序列不发散,但不足以实际上使其趋于一致。它实际上收敛到振荡状态,在1.6726450849432732.8804350135298153之间来回跳动。然而,阻尼变换在每一步都应用了两次,所以fixed-point只能看到序列中的每个其他元素 - 该子序列收敛于后者,即使序列整体无法收敛。

+1

另外,我怀疑它对低阶命令起作用的原因简直归结为低阶减震需要较少的事实,因此应用较少衰减的其他版本仍然能够通过。如果您进一步增加订单,您可能会发现需要更多的阻尼来抵消增加的无限冲击倾向。 – mokus 2011-02-23 03:07:53

+0

这是正确的。当我做同样的问题时,我发现当n增加一倍时,你需要增加1的平均衰减数。http://www.billthelizard.com/2010/08/sicp-145-computing-nth-roots.html – 2011-02-23 04:44:02

+0

@蜥蜴♦♦:不错的贴子。我很确定这样做的原因是因为这种方法的步骤是一种逼近牛顿 - 拉夫森步骤的非常迂回的方式。重复平均衰减m次与计算f(y)=(1 - 1/2^m)y + x /(2^m y ^(n-1))相同。令m为log2(n)使得阶跃函数f(y)=(1 - 1/n)y + x /(ny ^(n-1)),这正是Newton-Raphson所使用的。使用它的地板使它成为一个(足够好的)近似值,所以我会说你在帖子中的直觉是正确的。 – mokus 2011-02-23 13:51:39

相关问题