170 likes | 321 Views
土木 0703. 杨丹青 U200715361 包宇 U200715312 魏建 U200715241 郑志伟 U200715335 李英磊 U2007326 叶尔克西 U200715222 王嘉 U200717689. 问题提出. 用二分法求下列方程在所给区间上的根。 1.f(x)=x^3+3x+1 x∈[0,1) 2.f(x)=x^3-2sin(x) x∈[0.5,2]
E N D
土木0703 • 杨丹青 U200715361 • 包宇 U200715312 • 魏建 U200715241 • 郑志伟 U200715335 • 李英磊 U2007326 • 叶尔克西 U200715222 • 王嘉 U200717689
问题提出 用二分法求下列方程在所给区间上的根。 1.f(x)=x^3+3x+1 x∈[0,1) 2.f(x)=x^3-2sin(x) x∈[0.5,2] 3.f(x)=x+10+x*cos(50/x) x∈[120,130] 4.f(x)=9x^4+18x^3+38x^2-57x+14 x∈[0,1] 5.f(x)=x^8-36x^7+546x^6-4536x^5+22449x^ 4-67284x^4+118124x^2-109584x+40320=0 若将x^7前的系数改为-37,再求解。
分析 用二分法解方程,首先取所给区间端点值的函数值,并判断两函数值的符号关系。如果同号(函数在所给区间内单调),这在该范围内无根;如果都为0,表明其中至少有一个为方程的根,再进一步判断;如果异号,表明该范围内有实根,取两端点值平均值的函数值,并判断它和的两端点值函数值的符号关系,它与函数值异号的端点值形成新的取值范围,进一步判断,不断重复上述过程,直至满足某一条件为止。
算法设计 1.定义一个函数f(x) 2.输入x1,x2 3.比较f(x1)和f(x2)大小关系,如果同号(函数在所给区间内单调),这在该范围内无根;如果都为0,表明其中至少有一个为方程的根,再进一步判断;如果异号,表明该范围内有实根,取两端点值平均值的函数值(x=(x1+x2)/2),并判断它和的两端点值函数值的符号关系,它与函数值异号的端点值形成新的取值范围,进一步判断,不断重复该过程,直至f(x1)和f(x2)的差值不大于1e-5或f(x2)的值不大于1e-6为止。 4.如果因为满足第一个条件退出循环,则取x=(x1+x2)/2;如果因为满足第二个条件推出循环,则直接取x。 5.输出x的值。
代码和运行结果 • #include <stdio.h> • #include <math.h> • double f (double x) • { • double y; • y=x*x*x+3*x+1; • return (y); • } • main () • { • double f (double x); • double a=0.0, b=1.0,x; • if (f(a)>0* f(b)>0) • printf ("方程无解或有偶重根\n"); • else • {x=(a+b)/2; • while(f(x)>0.000001) • { • if (f(a)*f(x)<0) • b=x; • else • a=x; • x=(a+b)/2; • } • } • }
#include<stdio.h> • #include<math.h> • double f(double x) • {double y; • y=x*x*x-2*sin(x); • return(y); • } • void main() • {double x1=0.5,x2=2,x3,y1,y2,y3; • int i; • for(i=0;;i++) • {x3=(x1+x2)/2; • y3=f(x3);y2=f(x2);y1=f(x1); • if((fabs(y3)<=1e-6)||(fabs(x2-x1)<1e-6)) • {printf("the root is %f",x3); • break;} • else if(y1*y3<0) • x2=x3; • else x1=x3; • } • }
#include "stdio.h" • #include<math.h> • void main() • {float x1,x2,x; • float f(float x); • printf("Please enter values of x1,x2:"); • scanf("%f%f",&x1,&x2); • if(f(x1)*f(x2)>0.0) • printf("No root between the two numbers!"); • else if(f(x1)*f(x2)==0.0) • { if(f(x1)==0.0) • x=x1; • else • x=x2; • printf("the root is %f",x); • } • else • {do{x=(x1+x2)/2; • if(f(x1)*f(x)<0) • x2=x; • else • x1=x; • }while(fabs(x1-x2)>1e-5&&fabs(f(x))>1e-6); • if(fabs(f(x))>1e-6) • x=(x1+x2)/2; • printf("the root is %f",x); • } • } • float f(float x) • {float s; • s=x+10-x*cosh(50/x); • return(s); • }
#include<stdio.h> • #include<math.h> • void main() • {float a,b,x; • float f(float x); • printf("please enter the value of a,b(分隔符用逗号):"); • scanf("%f,%f",&a,&b); • if(f(a)*f(b)==0) • {if(f(a)==0)x=a; • if(f(b)==0)x=b; • printf("方程在区间[%f,%f]内的根为:x==%f",a,b,x); • } • else if(f(a)*f(b)<0) • {do • {x=(a+b)/2; • if(f(x)==0); • else if(f(a)*f(x)<0) • b=x; • else if(f(x)*f(b)<0) • a=x; • } • while(fabs(a-b)>1e-5&&fabs(f(x))>1e-6); • x=(a+b)/2; • printf("方程在区间[%f,%f]内的根为:x==%f",a,b,x); • } • else printf("在区间[%f,%f]内方程无解",a,b); • } • float f(float x) • {float m; • m=9*x*x*x*x+18*x*x*x+38*x*x-57*x+14; • return(m); • }
#include<stdio.h> • #include<math.h> • double f1(double x) • { • double y; • y=x*(x*(x*(x*(x*(x*(x*(x-36)+546)-4536)+22449)-67284)+118124)-109584)+40320; • return(y); • } • void main() • { • double a,b,x; • int i=0; • l:printf("input a: b:"); • scanf("%lf%lf",&a,&b); • if(f1(a)*f1(b)>=0) • { • printf("error\n"); • goto l; • } • x=a+(b-a)/2; • do{ • if(f1(x)*f1(a)>0) • a=x; • else if(f1(x)*f1(b)>0) • b=x; • else • break; • i++; • x=a+(b-a)/2; • }while(fabs(f1(x))>1e-10); • printf("the root is:%lf\nf:%lf",x,f1(x)); • }
总结 二分法的优点:操作简单,逻辑结构清晰,便于掌握。 二分法的缺点:解方程前,必须根据图形走势选择合适的区间;只能求实根,不能求复根;与牛顿迭代法等相比,收敛速度较小,仅为0.5。
感想与体会 二分法仅仅适用比较简单的方程求解。一旦所给的方程较复杂,无法直观的得到函数图形的走势,就必须与其他数学软件配合使用。因此,我们认为在实际应用中二分法并无太大的实用价值,它比较适合用来辅助计算方法入门者学习。