您的位置:首页 > 其它

算法设计与分析

2015-07-25 10:46 239 查看
多种算法求解非线性方程

1.内容分析

1.1非线性方程介绍

线性方程,就是因变量自变量之间的关系不是线性的关系,这类方程很多,例如平方关系、对数关系、指数关系、三角函数关系等等。求解此类方程往往很难得到精确解,经常需要求近似解问题。相应的求近似解的方法也逐渐得到大家的重视。

1.2非线性方程的数值解简介

20世纪60年代中期以后,发展了两种求解非线性方程组(1)的新方法。一种称为区间迭代法或称区间牛顿法,它用区间变量代替点变量进行区间迭代,每迭代一步都可判断在所给区间解的存在惟一性或者是无解。这是区间迭代法的主要优点,其缺点是计算量大。另一种方法称为不动点算法或称单纯形法,它对求解域进行单纯形剖分,对剖分的顶点给一种恰当标号,并用一种有规则的搜索方法找到全标号单纯形,从而得到方程(1)的近似解。这种方法优点是,不要求f(□)的导数存在,也不用求逆,且具有大范围收敛性,缺点是计算量大。

 

2.本次作业目的

通过课程设计,提高用计算机解决实际问题的能力,提高独立实践的能力,将课本上的理论知识和实际有机的结合起来,锻炼分析解决实际问题的能力。提高适应实际,实践编程的能力。在实际的编程和调试综合试题的基础上,把高级语言程序设计的思想、编程巧和解题思路进行总结与概括,通过比较系统地练习达到真正比较熟练地掌握计算机编程的基本功,为后续的学习打下基础。了解一般程序设计的基本思路与方法。更重要的是,比较多种算法解决同一问题的特点,对于不同算法的优点和缺点做详细分析,对其效率和正确性做系统分析,从中学习算法思想,达到进步的目的。

 

3.各种算法的原理及思路

3.1二分法

3.1.1二分法简介

二分法,又称分半法,是一种方程式根的近似值求法。对于区间[a,b]上连续不断且f(a) ·f(b)<0的函数y=f(x),通过不断地把函数f(x)的零点所在的区间一分为二,使区间的两个端点逐步逼近零点,进而得到零点近似值的方法叫做二分法(bisection)。

 

 

3.1.2二分法程序流程图

程序流程图如下:

 

 

 

3.1.3二分法源程序代码

#include <stdio.h> 

#include <math.h> 

double func(double x) //函数 

{

    return (1.5*x*x*x-7.8*x*x+16.2*x-14.6);

}

int main() 

{

    double a=1.5,b=3.5;//初始区间 

    double c;

    c=(a+b)/2.0; 

    while(fabs(func(c))>1e-6)

    {

        if(func(c)*func(b)<0) //确定新的区间 

            a=c; 

        if(func(a)*func(c)<0)

            b=c; 

        c=(a+b)/2; //二分法确定新的区间 

    }

    printf("二分法解方程:1.5*x*x*x-7.8*x*x+16.2*x-14.6\n");

    printf("结果:%0.6f\n",c); //输出解 

    return 0;

}

 

3.1.4程序运行结果

 

 

3.2弦截法

3.2.1弦截法简介

弦截法是一种求方程根的基本方法,在计算机编程中常用。他的思路是这样的:任取两个数x1、x2,求得对应的函数值f(x1)、f(x2)。如果两函数值同号,则重新取数,直到这两个函数值异号为止。连接(x1,f(x1))与(x2,f(x2))这两点形成的直线与x轴相交于一点x,求得对应的f(x),判断其与f(x1)、f(x2)中的哪个值同号。如f(x)与f(x1)同号,则f(x)为新的f(x1)。将新的f(x1)与f(x2)连接,如此循环。体现的是极限的思想。

 

3.2.2弦截法程序流程图

程序流程图如下:

 

 

 

3.2.3弦截法源程序代码

#include<stdio.h>

#include<math.h>

#define f(x) (1.5*x*x*x-7.8*x*x+16.2*x-14.6)

#define x0 0.5

#define x1 1.6

#define MAXREPT 1000

#define epsilon 0.00001

int main(void)

{

int i;

double x_k=x0,x_k1=x1,x_k2=x1;

for(i=0;i<MAXREPT;i++)

{

x_k2=x_k1-(f(x_k1)*(x_k1-x_k))/(f(x_k1)-f(x_k));     //迭代公式:Xk+1=Xk-(f(Xk)(Xk-Xk-1))/(f(Xk)-f(Xk-1)) k=1,2,3.....

if(fabs(x_k2-x_k1)<epsilon||fabs(f(x_k2))<epsilon)

{

printf("弦截法解方程:1.5*x*x*x-7.8*x*x+16.2-14.6\n");

printf("结果:%f\n",x_k2);

return;

}

x_k=x_k1;

x_k1=x_k2;

}

printf("After %d repeate,no solved.\n",MAXREPT);

}

 

3.2.4程序运行结果

 

 

3.3黄金分割法

3.3.1黄金分割法简介

由于公元前6世纪古希腊的毕达哥拉斯学派研究过正五边形和正十边形的作图,因此现代数学家们推断当时毕达哥拉斯学派已经触及甚至掌握了黄金分割。

公元前4世纪,古希腊数学家欧多克索斯第一个系统研究了这一问题,并建立起比例理论。公元前300年前后欧几里得撰写《几何原本》时吸收了欧多克索斯的研究成果,进一步系统论述了黄金分割,成为最早的有关黄金分割的论著。中世纪后,黄金分割被披上神秘的外衣,意大利数家帕乔利称中末比为神圣比例,并专门为此著书立说。德国天文学家开普勒称黄金分割为神圣分割。

到19世纪黄金分割这一名称才逐渐通行。黄金分割数有许多有趣的性质,人类对它的实际应用也很广泛。最著名的例子是优选学中的黄金分割法或0.618法,是由美国数学家基弗于1953年首先提出的,70年代在中国推广。

 

3.3.2黄金分割法程序流程图

程序流程图如下:

 

 

3.3.3黄金分割法程序源代码

#include <stdio.h> 

#include <math.h> 

double func(double x) //函数 

{

return (1.5*x*x*x-7.8*x*x+16.2*x-14.6);

}

int main() 

{

double a=1.5,b=3.5;//初始区间 

double t1,t2,c,root;

t1=a+(1-0.618)*(b-a);

t2=a+0.618*(b-a);

c=t1-t2;

while(fabs(c)>1e-6)

{

if(func(t1)*func(t2)<0) //确定新的区间

{

a=t1; 

b=t2;

}

else if(func(t1)*func(a)>0)

{

a=t2;

}

else if(func(t1)*func(a)<0)

{

b=t1;

}

else if(func(b)*func(t2)>0)

{

b=t1;

}

else if(func(b)*func(t2)<0)

{

a=t2;

}

t1=a+(1-0.618)*(b-a);

t2=a+0.618*(b-a);

c=t1-t2;

}

root=(t1+t2)/2;

printf("黄金分割法解方程:1.5*x*x*x-7.8*x*x+16.2*x-14.6\n");

printf("结果:%0.6f\n",root); //输出解 

return 0;

}

 

3.3.4程序运行结果

 

 

 

3.4抛物线法

3.4.1抛物线法简介

抛物线法是求无约束一维极值的一种方法,也叫二次插值法,其理论依据为二次多项式可以在最优点附近较好的逼近函数的形状,做法是在函数的最优点附近取三个构造点,然后用这三个点构造一条抛物线,把这条抛物线的极值点作为函数的极值点的近似。

每次构造一条抛物线后,抛物线的极值点就可作为一个新的构造点,新的构造点与原来的三个构造点经过某种算法,得到下一步抛物线逼近的三个构造点,这就是抛物线法的算法过程。

弦截法师用过两点的直线与x轴交点来近似代替方程f(x)=0与x轴的交点。抛物线法则是过曲线上的三点作一条抛物线,用抛物线与x轴的一个交点来作为f(x)=0与x轴交点的近似值。

 

3.4.2抛物线法程序流程图

 

 

3.4.3抛物线法源程序

#include<stdio.h>

#include<math.h>

#define f(x) (1.5*x*x*x-7.8*x*x+16.2*x-14.6)

#define epsilon 0.00001

int main(void)

{

int x0=1.5,x1=3.5,x2=2.5,x31,x32,x3;

double f1,f2,f3,tol=1.0;

double A,B,C,root=1.0;

f1=(f(x2)-f(x1))/(x2-x1);

f2=(f(x1)-f(x0))/(x1-x0);

f3=(f1-f2)/(x2-x0);

A=f(x2);

B=f1+f3*(x2-x1);

C=f3;

x31=x2+(sqrt(pow(B,2)-4*A*C)-B)/(2*C);

x32=x2-(sqrt(pow(B,2)-4*A*C)+B)/(2*C);

 

if(abs(x31-x2)<abs(x32-x2))

x3=x31;

else if(abs(x31-x2)>=abs(x32-x2))

x3=x32;

root=x3;

while(tol>epsilon)

{

x0=x1;

x1=x2;

x2=root;

f1=(f(x2)-f(x1))/(x2-x1);

f2=(f(x1)-f(x0))/(x1-x0);

f3=(f1-f2)/(x2-x0);

A=f(x2);

B=f1+f3*(x2-x1);

C=f3;

x31=x2+(sqrt(pow(B,2)-4*A*C)-B)/(2*C);

x32=x2-(sqrt(pow(B,2)-4*A*C)+B)/(2*C);

if(abs(x31-x2)<abs(x32-x2))

root=x31;

else if(abs(x31-x2)>=abs(x32-x2))

root=x32;

tol=abs(root-x3);

}

printf("抛物线法解方程:1.5*x*x*x-7.8*x*x+16.2-14.6\n");

printf("结果:%.6f\n",x3);

return(0);

}

 

3.4.4程序运行截图

 

 

4.心得体会

在计算机软件专业中,算法分析与设计是一门非常重要的课程,很多人为它如痴如醉。很多问题的解决,程序的编写都要依赖它,在软件还是面向过程的阶段,就有程序=算法+数据结构这个公式。算法的学习对于培养一个人的逻辑思维能力是有极大帮助的,它可以培养我们养成思考分析问题,解决问题的能力。 

如果一个算法有缺陷,或不适合某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂性和时间复杂度来衡量。算法可以使用自然语言、伪代码、流程图等多种不同的方法来描述。计算机系统中的操作系统、语言编译系统、数据库管理系统以及各种各样的计算机应用系统中的软件,都必须使用具体的算法来实现。算法设计与分析是计算机科学与技术的一个核心问题。因此,学习算法无疑会增强自己的竞争力,提高自己的修为,为自己增彩。

非线性方程的数值求解已经趋于成熟,但对于较高阶数的高次方程的求解,还存在一些挑战,对于计算机软件专业的学生而言,掌握扎实的数学功底是非常重要的,扎实的数学根基是算法设计与分析的基础,是算法工程师的必要先修课。

算法这个词是在我在大学第一次C语言课上听到的,当时老师讲的是程序=算法+数据结构,算法是一个程序的灵魂。当时我什么也不懂,不知道什么叫数据结构,什么叫算法,它们是干什么的我也不明白。然而经历了大学三年的学习,现在的我对算法有了一个较为清晰的认识,对于它的作用也有了深刻的体会。

经过一学期的算法学习,我对算法的了解进一步加深,曾经学习过的内容得到进一步巩固,同时没有接触的内容也让我有了新的认识。作为一名计算机专业的学生,算法是一门基础学科,它里面包含的思想无处不在,学好算法分析,对于在自己的方向上获得启示,体会更深有着重大作用。所以,我们应该培养对算法的兴趣,将算法的运用融入到生活当中,比如找钱问题就是个很好的例子,通过具体的生活实例来让算法变得更加有魅力,有吸引力,以此来激发对算法的兴趣。

本次作业我并未选择课堂上学习的贪心算法、分治算法等,这与个人选题较晚和自我创新意识较强有较大关系。我选择了用数学方法来解决问题的算法,选择了四种算法来求解同一个高次方程的问题。程序编写条理清晰,看上去简单,但实际上是包含了较复杂的认为分析推理过程的,通过这次的算法大作业,对算法设计与分析这门课程有了较大程度的认识,对其中的算法思想有了较强的认识,希望在以后的学习生活中,能够通过解决实际问题而将学到的只是用上,不断进步!

 

5.参考文献

[1]王晓东. 《算法设计与分析》. 清华大学出版社. 2014年2月.

[2]Thomas H.Cormen Charles E.Leiserson. Ronald L.Rivest Clifford Stein. 《算法导论》. 机械工业出版社. 2014年1月.

[3]王晓东. 《算法设计与分析习题解答》. 清华大学出版社. 2014年2月.

[4]金聪 熊盛武. 《数值分析》. 武汉理工大学出版社. 2004年12月. 

[5]严蔚敏 吴伟民. 《数据结构》. 清华大学出版社. 2011年11月.

[6]严蔚敏 吴伟民. 《数据结构题集》. 清华大学出版社. 2011年11月.

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: