抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

以前困惑于求各种根式求值,现在学了牛顿迭代法,下次再求根式我就直接手撕根号了。

铺垫

现在让你求11\sqrt{11} 是多少?硬算的话肯定不行,估算大概是在9\sqrt{9}附近,现在画出f(x)=xf(x)=\sqrt{x}的函数图像,再标记9\sqrt{9}的位置:

image-20210720102712382

在点(9,3)做切线L(x)L(x),明显看出L(x)L(x)f(x)f(x)在点(9,3)重合,两条线十分接近点(11,11)(11,\sqrt{11}) ,两条线之间的间隔就是估算的误差,算出切线L(x)L(x)在x=11时的函数值,就是f(x)f(x)的近似解。

因为求该点切线需要用到该点的斜率,我们先求导算出斜率:

f(x)=12xf(9)=129=16f'(x)=\frac{1}{2\sqrt{x}}\\ f'(9)=\frac{1}{2\sqrt{9}}=\frac{1}{6}

将斜率带入切线方程:

yy0=k(xx0)y3=16(x9)y=32+x6L(x)=32+x6y-y_0=k(x-x_0)\\ y-3 = \frac{1}{6}(x-9)\\ y=\frac{3}{2}+\frac{x}{6}\\ L(x) = \frac{3}{2}+\frac{x}{6}

将x=11带入切线方程

L(11)=116+32=103L(11)=\frac{11}{6}+\frac{3}{2}=\frac{10}{3}

所以11\sqrt{11}近似的等于103\frac{10}{3},事实上,你可以使用计算器去校验一下, 由计算器求得的结果是3.317(精确到小数点后第3位),所以我们的计算结果是非常不错的。

牛顿迭代法

在求一个复杂的方程的时候,想简单的估算一下,就可以按照下面的方法做:

image-20210720153943329

y=f(x)y=f(x)上任意选一个x=a,作其切线L(x)L(x)。函数在a点的函数值并不等于零,可以说是x=a个近似解,但误差太大了,我们要让函数值等于0。往左可以看到x=b时,f(b)的函数值更接近0了,这时b这个近似解比a误差更小,我们先把b这个点算出来,怎么求b的值呢?

b点是切线方程L在x轴上的截距,令切线方程中的L(x)=0L(x)=0,即可求出x轴的截距。

L(x)=f(a)+f(a)(xa)0=f(a)+f(a)(xa)x=af(a)f(a)L(x)=f(a)+f'(a)(x-a)\\ 0=f(a)+f'(a)(x-a)\\ x=a-\frac{f(a)}{f'(a)}

所以下一个点的点b计算公式:

b=af(a)f(a)b=a-\frac{f(a)}{f'(a)}

算出点b的点之后继续将b带入f(x)中试试点b的函数值有没有更趋近于0,继续作点b的切线重复第一步,循环往复,最终求出来的值b是个比之前更好的近似解。

代码实现

import math


# 求导
def numerical_diff(f, x):
    h = 1e-10
    return (f(x + h) - f(x)) / h


# 牛顿迭代法实现
def solution(a, f):
    b = 0
    Delta = 1
    while Delta > 0.000001:
        b = a - f(a) / numerical_diff(f, a)
        Delta = f(b)
        a = b
    return b


def fun1(x):
    return x ** 5 + 2 * x - 1


def fun2(x):
    return x - math.cos(x)


fun1_ret = solution(0, fun1)
print("x**5+2*x-1 的近似解为:", fun1_ret)

fun2_ret = solution(math.pi / 2, fun2)
print("x-cos(x) 的近似解为:", fun2_ret)

# output:
# x**5+2*x-1 的近似解为: 0.48638904079265016
# x-cos(x) 的近似解为: 0.7390851781433039
  • 参考资料:《普林斯顿微积分读本》

评论