CG@CPPBLOG

/*=========================================*/
随笔 - 76, 文章 - 39, 评论 - 137, 引用 - 0
数据加载中……

我的SICP习题答案(1.7)

对于正文中的 good-enough? 谓词,设所求 x 的真实平方根为 xt,那么我们的依据是当 guess 从 1 趋向与 xt 的平方差 小于 c(0.001) 时,guess 近似于 xt。实际当 xt^2 也就是 x 足够小时, guess 会 逐渐稳定在 √c 附近。从下面实验可以看出:

> (sqrt (square 0.1))
0.10032578510960607
> (sqrt (square 
0.05))
0.054237622808967656
> (sqrt (square 
0.01))
0.03230844833048122
> (sqrt (square 
0.005))
0.031515954454847304
> (sqrt (square 
0.001))
0.031260655525445276
> (sqrt (square 
0.0001))
0.03125010656242753
>
 
因为 guess^2 < c + x , 当 x < c 时,guess 就更多的依赖于 c 了。

对于特别大的数,由于浮点数在特别大时,离散性非常明显,相邻的两个数之间的差距会非常大,导致 |guess^2 - x| 始终 大于 c,计算便进入了 无限循环。

比如计算 (sqrt 1e300)

使用变化率改进后的代码如下:

(define (sqrt-new x)
  (sqrt-iter-new x 
1.0 x))

(define (sqrt-iter-new s1 s2 x)
  (if (enuf-new? s1 s2)
      s2
      (sqrt-iter-new s2 (improve s2 x) x)))

(define (enuf-new? s1 s2)
  (< (/ (abs (- s1 s2)) s1) 
0.001))

可以测算几个数,验证结果还是比较好的。

> (sqrt-new (square 1e150))
1.0000000000084744e+150
> (sqrt-new (square 
1e-150))
1.0000000000084744e-150


posted on 2008-03-11 00:07 cuigang 阅读(1621) 评论(2)  编辑 收藏 引用 所属分类: Lisp/Scheme我的SICP答案

评论

# re: 我的SICP习题答案(1.7)  回复  更多评论   

我用的DrScheme (#lang planet neil/sicp)
我定义的名字是SQRT,程序和你的殊途同归
比较奇怪的是
如果我用(SQRT 1e8)没问题
如果我用(SQRT 100000000)就不行了,卡住了
如果我用(SQRT 100000000.0)又可以了
这种现象有点没头绪,不知道你的系统会不会这样
2010-02-01 12:08 | mxj

# re: 我的SICP习题答案(1.7)  回复  更多评论   

@mxj

(define (sqrt-new x)
(sqrt-iter-new x 1.0 x))

这句估计你写成了
(define (sqrt-new x)
(sqrt-iter-new x 1 x))

用了整数 1 而不是浮点数 1.0
2010-02-19 22:21 | cuigang

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理