F#实现二分法求方程的根

简介: 在不少工程问题中,我们需要求某一个方程f(x)的根,对于一元一次方程或者二次方程,我们可以利用公式非常方便的求出根。而对于高次方程或非线性方程,求根往往就没有现成的求根公式可以套用,而需要借助数值方法来进行求解。

     在不少工程问题中,我们需要求某一个方程f(x)的根,对于一元一次方程或者二次方程,我们可以利用公式非常方便的求出根。而对于高次方程或非线性方程,求根往往就没有现成的求根公式可以套用,而需要借助数值方法来进行求解。一般来说,对于一个连续的函数来说,如果存在两个点a和b,有f(a)和f(b)异号,那么理论上就存在一个根介于[a,b]之间,设为c,那么f(c)=0。举例来说,如果求x^3-1 这个函数,由于f(0) = -1 ,而f(2)=7,即f(0)*f(2) <0 ,那么说明在[0,2]之间必定存在一个根,根据图形,结合经验,可以判断出根为1。

1(29).jpg    那么这个根如何通过计算机程序来实现呢?那么首先需要了解一下求根算法:

1 二分法(Bisection Method)

     在数据结构和算法中,有一种算法也叫二分法,他可以用于快速查找。类似的,二分法也可以用于方程求根上。在https://x-engineer.org/官网上,有一篇解说二分法的文章,感觉非常详细,其中的核心过程如下图所示:

2(24).jpg

     在二分法当中,每一次迭代,搜索区间的长度就会缩减一半,这是一个指数级的缩减。因此,即使给定的初始搜索区间比较大,但经过二分法多次迭代后也可以迅速缩减,得到一个非常精准的结果。它和泰勒级数一样,除了能得到一个足够精确的值之外,还能得到误差的范围。详细的过程可参考:

https://x-engineer.org/undergraduate-engineering/advanced-mathematics/numerical-methods/the-bisection-method-for-root-finding

2 二分法实现

     根据上面的二分法算法过程,这里选择F#语言进行二分法求根程序实现。通过总结多种二分法算法描述,将二分法算法总结如下:

第一步:给出一个初始搜索区间[a,b]和精确度eps,如0.0001,使得f(a)*f(b)< 0 。

第二步:计算中间值 c=(a+b)/2 。

第三步:判断闭区间的长度b-a和精确度eps的关系,当闭区间长度>e的时候,返回第二步计算c。当闭区间长度<e的时候,停止迭代。输出结果c。

第四步:求出f(c)的值,如果f(a)*f(c)< 0 ,那么在[a,c]区间进行搜索;否则在[c,b]区间进行搜索。

    这个过程F#代码如下:

letrecroots ( f , x1 , x2 , eps ) =letm= (x1+x2) /2.if (abs(x2-x1 )<eps ) thenmelseif ( f(x1) *f(m) <0. ) thenroots(f,x1,m,eps)
elseroots(f,m,x2,eps)

3 求根验证

     为了验证二分法算法是否可以正确工作,下面给出函数进行验证:

lettestRoots=letfx=x**2.-4.letr=roots(f,-3.,3.,0.001) 
printfn"%O"r//-1.9998779296875letfx=x**2.-4.letr=round(roots(f,0.,3.,0.001))
printfn"%O"r//2letfx=sin(x**2.) -0.7letr=roots(f,-3.,3.,0.001) 
printfn"%O"r//0.8807373046875

    从上述测试可知,x ^2 - 4 = 0  的根,如果在[-3,3]上虽然有2个根,但是程序只能求出一个根 -1.9998779296875 ,理论解析解为 - 2 。如果将搜索范围给定到[0,3],那么可以求出另外一个根,这里用round函数进行处理,四舍五入到 2 。最后一个sin(x^2) - 0.7 = 0 的根,在[-3,3]区域求出一个根0.8807373046875 。实际上,通过绘图可知,在这个区间会有多个根:

3(18).jpg

   因此,具体的根,需要结合图形来给定初始搜索空间,这往往决定着求出的是哪个根

相关文章
|
2月前
|
人工智能 测试技术 Windows
【深度优先搜索】【树】【状态压缩】2791. 树中可以形成回文的路径数
【深度优先搜索】【树】【状态压缩】2791. 树中可以形成回文的路径数
|
2月前
|
算法 测试技术
【动态规划】【广度优先搜索】【状态压缩】847 访问所有节点的最短路径
【动态规划】【广度优先搜索】【状态压缩】847 访问所有节点的最短路径
|
2月前
|
测试技术
【动态规划】【组合数学】1866. 恰有 K 根木棍可以看到的排列数目
【动态规划】【组合数学】1866. 恰有 K 根木棍可以看到的排列数目
|
2月前
|
人工智能 算法 BI
【深度优先搜索】【C++算法】834 树中距离之和
【深度优先搜索】【C++算法】834 树中距离之和
|
6月前
|
算法 索引
算法:二分查找算法/朴素二分/查找区间左右端点二分
算法:二分查找算法/朴素二分/查找区间左右端点二分
|
11月前
7-157 求一元二次方程的根
7-157 求一元二次方程的根
71 0
|
11月前
leetcode160–相交链表(最优解/双指针)
leetcode160–相交链表(最优解/双指针)
|
算法
一道线段树相关算法题
每个方块都从一个比目前所有的落地方块更高的高度掉落而下。方块沿 y 轴负方向下落,直到着陆到 另一个正方形的顶边 或者是 x 轴上 。一个方块仅仅是擦过另一个方块的左侧边或右侧边不算着陆。一旦着陆,它就会固定在原地,无法移动。
64 0
一道线段树相关算法题
|
机器学习/深度学习 算法
斐波拉契数列的递推递归求解算法
斐波拉契数列的递推递归求解算法
77 0
|
算法 关系型数据库 MySQL
前缀和和差分和dijkstra算法和二分算法和floyd算法
前缀和和差分和dijkstra算法和二分算法和floyd算法