scheme寻找方程根与函数不动点

本节的主要内容在于lambda函数和let函数,通过两种新的函数形式减少了定义的使用,对过程设计进行了简化。
lambda函数用于减少define的使用,使得过程的编制更加符合直觉,通过lambda(x)(fx)的形式可以减少很多函数体外的定义过程。
let函数更多用于定义局部变量,通过let体内的定义可以直接完成局部变量的运算,但需要注意区分let函数体内外的运算过程区分。
新函数与之前应用的函数无太大区别,属于是之前函数的简化,因此无太多练习。

补充了几个算法,关于寻找方程根和函数不动点的内容。方程根值的寻找和之前的平方根求值思路是一致的,通过不断缩小区间范围,找到0点的对应的具体值。
不动点的概念如下,若x满足方程f(x)=x且反复的应用f:f(x)、f(f(x))、f(f(f(x)))…到最后其值无明显变化时,可以认为找到了函数的不动点。
针对两种函数的练习如下:
1.35 证明黄金分割率φ是变换1+1/x的不动点,并通过过程计算。
证明过程很简单,根据黄金分割率φ的特性φ²=φ+1即可证明,计算过程如下:

点击查看代码
(define tolerance 0.0001)
(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))
(fixed-point (lambda (x) ( + 1.0 ( / 1.0 x))) 1.0)
1.6180555555555556

1.36 要求修改fixed-point过程,使其能够打印出计算中产生的近似值序列。并找到log(1000)/log(x)的不动点。
前半个问题只需要在原有函数中添加newline和display函数即可解决:

点击查看代码
(define tolerance 0.0001)
(define (fixed-point f first-guess)
    (define (close-enough? v1 v2)
        (< (abs ( - v1 v2)) tolerance))
    (define (try guess)
        (newline)
        (display guess)
        (let ((next (f guess)))
            (if (close-enough? guess next)
                next
                (try next))))
    (try first-guess))
后半个问题题目要求分别试验用平均阻尼和不用平均阻尼时的计算步数(平均阻尼即将每次产出的新的guess进行二次变换,如取其和前一个guess的平均数) 不用平均阻尼时:
点击查看代码
> (fixed-point (lambda(x) ( / (log 1000) (log x))) 2.0)
2.0
9.965784284662087
3.004472209841214
6.279195757507157
3.759850702401539
5.215843784925895
4.182207192401397
4.8277650983445906
4.387593384662677
4.671250085763899
4.481403616895052
4.6053657460929
4.5230849678718865
4.577114682047341
4.541382480151454
4.564903245230833
4.549372679303342
4.559606491913287
4.552853875788271
4.557305529748263
4.554369064436181
4.556305311532999
4.555028263573554
4.555870396702851
4.555315001192079
4.5556812635433275
4.555439715736846
4.555599009998291
4.555493957531389
4.555563237292884

使用平均阻尼时:

点击查看代码
(fixed-point (lambda(x)(average x  ( / (log 1000) (log x)))) 2.0)

2.0
5.9828921423310435
4.922168721308343
4.628224318195455
4.568346513136242
4.5577305909237005
4.555909809045131
4.555599411610624
4.5555465521473675

可见使用平均阻尼后减少了很多计算的步数,算法占用空间和时间步数都有所节省。

1.37 要求解一个无穷连分式,

QianJianTec1764840055127

按照要求编写过程,并根据题目要求代入n=1、d=1进行计算:

点击查看代码
(define (cont-frac n d k)
    (define (try next k)
        (let ((result ( / n (+ d next))))
            (if (< k 1)
                result
                (try result (- k 1))
            )
        )
    )
    (try 0.0 k)
)
> (cont-frac 1.0 1.0 10)
0.6180555555555556
> (cont-frac 1.0 1.0 100)
0.6180339887498948

1.38 要求同上一题,不过这回需要借e-2的连分式,此处我编写的程序结果持续振荡,我也在找原因,如有高手看出问题烦请提点,感谢!

点击查看代码
(define (3n+2? x)
    ( = (remainder (- x 2) 3) 0)
)
(define (mod3 x)
    ( / (- x 2) 3)
)
(define (cont-frac n d k)
    (define (try next k)
        (cond ((3n+2? k)
                (let((result (/ n (+ (* (+ (mod3 k) 1) 2) next))))
                    (if (= k 1)
                    result
                    (try result (- k 1))
                )
                ))
                (else
                  (let((result (/ n (+ d next))))
                    (if (= k 1)
                    result
                    (try result (- k 1))
                    )
                  ))))
    (try 0.0 k)
)

1.39 对正切函数的连分式定义过程
没啥好说的,和前面一样。

点击查看代码
(define (square x) (* x x))
(define (tan-cf x k)
    (define (try next k)
        (let ((result ( / (square x) (- (- (* 2 k) 1) next))))
            (if (= k 2)
                (/ x (- 1 result))
                (try result (- k 1))
            )
        )
    )
    (try 0.0 k)
)
posted @ 2025-12-04 18:24  檐上落白luckin  阅读(4)  评论(0)    收藏  举报