算法之牛顿法求平方根+立方根
author:onceday date:2022年6月8日
1.基于Scheme语言
牛顿法基于以下几步来求出平方根:
- 先给出一个猜测值y
- 判断猜测值y是否与目标值非常接近,已经足够好,可以直接使用。
- 如果不是足够好,则需要进一步改进猜测值。
- 递归执行,直到得出足够好的值。
将上面的步骤写成代码如下:
;;;定义求平方根的迭代过程
(define (sqrt_iter guess x)
(if (good_enough? guess x)
guess
(sqrt_iter (improve guess x) x)
)
)
如何判断猜测值是否足够好呢?可以根据猜测值的平方与被开方数之差小于某个固定值,如0.0001;
;;;定义猜测值是否很好的检测方式
(define (good_enough? guess x) (< (abs (- (square guess) x)) 0.001))
;;;定义绝对值计算
(define (abs x)
(if (< x 0)
(- x)
x))
;;;定义平方值计算
(define (square x) (* x x))
但是,这对于较大的数来说,不错,因为0.0001相对10,10000等来说是很小的。
但对于0.001来说,其精度就太低了。
因此可以使用百分比来衡量是否足够好,即监视猜测值在从一次迭代到下一次迭代的变化情况,当改变值相对于猜测值的比率很小时就结束。
;;;定义第二种猜测值是否很好的检测方式,利用百分比
(define (good_enough? guess x) (< (/ (abs (- (improve guess x) guess)) guess) 0.0001))
在这个基础上还可以实现求立方根的算法:
- 使用百分比确定是否足够好
- 近似值由公式 x / y 2 + 2 y 3 \frac{x/y^2+2y}{3} 3x/y2+2y计算而来,y是猜测值,x是被开立方数
;;;定义求立方根的迭代过程
(define (cube_iter guess x)
(if (good_enough? guess x)
guess
(cube_iter (improve guess x)
x)))
;;;定义改进猜测的方式
(define (improve guess x)
(/ (+ (/ x (square guess)) (* 2 guess)) 3))
;;;定义平均值计算
(define (average x y) (/ (+ x y) 2))
;;;定义第二种猜测值是否很好的检测方式,利用百分比
(define (good_enough? guess x) (< (/ (abs (- (improve guess x) guess)) guess) 0.0001))
;;;定义绝对值计算
(define (abs x)
(if (< x 0)
(- x)
x))
;;;定义平方值计算
(define (square x) (* x x))
;;;定义平方根计算,默认初始猜测值1.0
(define (cube_root x) (cube_iter 1.0 x))