Scheme立方根函数精度不足问题排查及优化咨询(SICP习题1.8)
SICP习题1.8:立方根函数精度问题分析与优化
先贴出你编写的立方根计算代码:
(define (square x) (* x x)) (define (abs x) (if (< x 0) (- x) x)) (define (cube x) (* x x x)) (define (cube-root-itr guess x) (if (good-enough? guess x) guess (cube-root-itr (improve guess x) x))) (define (improve guess x) (/ (+ (* 2 guess) (/ x (square guess))) 3)) (define (good-enough? guess x) (< (abs (- (cube guess) x)) 0.0000000001)) (define (cube-root x) (cube-root-itr 1.0 x)) (cube-root 9)
为什么无法返回更精确的结果?
你的good-enough?函数用的是绝对误差判断逻辑:只要(cube guess)和目标值x的差值绝对值小于0.0000000001就停止迭代。这种方式存在明显局限:
- 当迭代到后期,
guess已经非常接近真实立方根,此时(cube guess)和x的差值会卡在阈值附近,无法继续迭代逼近更精准的值; - 绝对阈值对不同量级的数值适应性差,不过对于计算9的立方根来说,核心限制就是这个绝对误差终止条件。
如何优化?
核心优化思路是把绝对误差判断改成相对误差判断——也就是判断两次迭代的猜测值之间的相对变化是否足够小。这样能更准确地反映迭代的收敛程度,避免绝对阈值带来的限制。
优化后的代码如下:
(define (square x) (* x x)) (define (abs x) (if (< x 0) (- x) x)) (define (cube x) (* x x x)) ; 迭代函数新增前一次猜测值参数,用于对比相对变化 (define (cube-root-itr prev-guess guess x) (if (good-enough? prev-guess guess) guess (cube-root-itr guess (improve guess x) x))) ; 优化后的终止条件:判断两次猜测的相对变化率 (define (good-enough? prev-guess guess) (< (abs (/ (- guess prev-guess) guess)) 0.0000000000001)) (define (improve guess x) (/ (+ (* 2 guess) (/ x (square guess))) 3)) ; 初始调用时,用一个和初始猜测值差异较大的数作为前一次猜测 (define (cube-root x) (cube-root-itr 0.0 1.0 x)) (cube-root 9)
优化后,函数会在两次猜测值的相对变化足够小时停止,能迭代到更接近真实值的结果,精度会明显提升。
内容的提问来源于stack exchange,提问作者Mohammad Abdullah Khan
相关产品推荐
相关产品推荐

