C语言课程设计.docx
《C语言课程设计.docx》由会员分享,可在线阅读,更多相关《C语言课程设计.docx(18页珍藏版)》请在冰豆网上搜索。
C语言课程设计
C语言课程设计报告
指导老师:
报告人:
学号:
班级:
摘要
选作第6题、第35题,并对第6题进行了改进。
第6题,即用二分法求方程2x3-4x2+3x-6=0在(-10,10)之间的根。
第35题,即选择合适的数,并对生成的数进行由大到小的排序,核心算法之一为起泡法。
对第6题进行改进后,可以推广到解任意一元一次、一元二次和一元三次方程,其中求解一元三次方程使用到了二分法。
本文的三个代码均采用VS2015编写,格式和vc++略有不同。
正文
6.编写程序,用二分法求方程2x3-4x2+3x-6=0在(-10,10)之间的根。
本题较为简单,核心思想为利用二分法来不断缩小根的取值范围,最终使结果达到合理的精度。
需要注意的是:
在设定最终判断是否满足循环条件时,应该把条件设定为“是否小于4*10-7或更小”,如果把条件设定为“是否小于1*10-6”第七位小数则可能进位(调试程序时发现VS2015的中间过程值保留了16位小数)。
流程图如下:
运行结果如下:
35.个、十、百、千重新排列,符合条件的数大小排序问题。
把千位数字和十位数字重新组成一个新的十位数ab(新十位数的十位数字是原4位数的千位数字,个位数字是原4位数字的十位数字);把个位数字和百位数字组成的两个十位数cd(新十位数的十位数字是原4位数的个位数字,个位数字是原4位数的百位数字)。
如果新组成的两个十位数ab>cd,ab必须是偶数,且能被五整除,cd必须是奇数,同时,两个新的十位数字均不为0。
将满足此条件的4位数按从大到小的顺序输入数组中,并计算满足上述条件的4位数的个数。
本题较第6题难度略有增加,可以对数组a,b,c,d循环赋值并判断是否满足题目条件,其中条件“ab必须是偶数,且能被五整除”暗示b为0。
如果满足条件则另计数器sum(初值为0)增加1,并记录下原四位数,所以原四位数的第一个有效元素为e[1],最后一个有效元素为e[sum]。
在根据起泡法将它们按由大到小的顺序排列。
流程图如下:
运行结果如下:
6题改进方案
第6题的求根方法试用范围很小,结果的得出取决于恰当的初始给定的范围,倘若给定的范围内有两个或者三个根则只能求出一个。
因此对第六题进行了修改使它适用于所有的一元三次、一元二次和一元一次方程。
大体思路如下:
1.判断a是否为0,如若为0再判断b是否为0,b不为0则方程为二次方程,利用判别式可以判断它有几个根,再用求根公式求出;b如果为0判断c是否为0,c如果不等于0,方程式一元一次方程,根则为:
-c/d;如果c为0,d不为0则报错,d=0则显示“0确实等于0”
2.a如果小于0则令a=-a,b=-b,c=-c,d=-d,目的是把它传化成三次项系数为正数的方程。
3.对三次函数求导得到它的导数y’=3ax2+2bx+c,计算导函数的判别式,如果小于等于0则方程仅有一个实数根。
判别式大于0时,导函数存在极大值和极小值,其中极大值点小于极小值点。
根据极大值与极小值的关系可分为如下五种情况。
图1极大值小于0,有一个不同的实根图2极小值大于0,有一个不同的实根
图3极大值等于0,有两个不同的实根图4极小值等于0,有两个不同的实根
图5极大值大于0,极小值小于0,有三个实根
4.利用二分法求解三次方程的根,其中图5的令min1=极大值点,每次自减1直至f(min1)<0,令max1=极小值点,每次自增1直至f(max1)>0。
图3和图4的方法与之类似。
需要注意的是:
当有根为0时,由于二分法求得是近似值,当根为0时,显示的结果可能为“-0.000000”不符合大家习惯,因此要将它转为“0.000000”。
流程图如下:
运行结果(依次为求解一元三次、一元二次和一元一次方程)如下:
附录
6题代码
#include
#include
#include
intmain()
{
doublem=10,n=-10,a=2,b=-4,c=3,d=-6,x,y,y1;
printf("求解方程2x^3-4x^2+3x-6的根\n");
x=(m+n)/2;
do
{
y=a*x*x*x+b*x*x+c*x+d;
y1=a*m*m*m+b*m*m+c*m+d;
if(y*y1<0)
{
n=x;
x=(m+n)/2;
}
else
{
m=x;
x=(m+n)/2;
}
}while(fabs(y)>1e-7);
printf("方程在(-10,10)中的根为:
%lf\n",x);
system("color3");
system("pause");
return0;
}
35题代码
#include
#include
intmain()
{
inta[10],b[10],c[10],d[10],e[10000],i,j,k,l,sum=0,t;
for(i=0;i<=9;i++)
{
a[i]=i;
for(j=0;j<=9;j++)
{
b[j]=j;
for(k=0;k<=9;k++)
{
c[k]=k;
for(l=0;l<=9;l++)
{
d[l]=l;
if((d[l]%2==1)&&(c[k]!
=0)&&(b[j]==0)&&(a[i]!
=0)&&((a[i]*10+b[j])>(c[k]*10+d[l])))//ab既要被5整除,又要是偶数.所以b只能是0
{
sum=sum++;
e[sum]=a[i]*1000+d[l]*100+b[j]*10+c[k];
}
}
}
}
}
for(j=0;j<=sum-2;j++)
{
for(i=1;i+j{
if(e[i+1]>e[i])
{
t=e[i+1];
e[i+1]=e[i];
e[i]=t;
}
}
}
printf("按从大到小的顺序排列:
\n");
for(i=1;i<=sum;i++)
{
printf("%d",e[i]);
if(i%10==0)
printf("\n");
else
if(i==sum)
printf("\n");
else
printf(",");
}
printf("一共有%d个这样的数\n",sum);
system("color3");
system("pause");
return0;
}
6题改进代码
#include
#include
#include
#include
intmain()
{
doublef(doublex,doublea,doubleb,doublec,doubled);
doubleerfenfa(doublemax,doublemin,doublea,doubleb,doublec,doubled);
doublea,b,c,d;
doublex1,x2,x3,panbieshi,max,min,max1,min1,t;
printf("请输入三次项系数:
");
scanf_s("%lf",&a);
printf("请输入二次项系数:
");
scanf_s("%lf",&b);
printf("请输入一次项系数:
");
scanf_s("%lf",&c);
printf("请输入常数项系数:
");
scanf_s("%lf",&d);
if(a<0)
{
a=-a;
b=-b;
c=-c;
d=-d;
}
if(a==0)
{
if(b==0)
{
if(c==0)
{
if(d==0)
printf("0确实等于0");
else
printf("\a不要逗我,我知道%lf不等于0的",d);
}
else
{
x1=-(d/c);
if(fabs(x1)<1e-6)
x1=0;
printf("这是一个一次方程哟!
\n根为:
%lf",x1);
}
}
else
{
panbieshi=c*c-4*b*d;
printf("这是一个二次方程。
");
if(panbieshi<0)
printf("然而不幸的是方程没有实数根。
");
else
if(panbieshi==0)
{
x1=-c/2/b;
if(fabs(x1)<1e-6)
x1=0;
printf("方程有两个相等的实数根。
\n根为:
%lf",x1);
}
else
{
x1=(-c+sqrt(panbieshi))/2/b;
x2=(-c-sqrt(panbieshi))/2/b;
if(fabs(x1)<1e-6)
x1=0;
if(fabs(x2)<1e-6)
x2=0;
printf("方程有两个不相等的实数根。
\n根分别为为:
%lf,%lf",x1,x2);
}
}
}
else
{
panbieshi=4*b*b-12*a*c;
if(panbieshi>0)
{
min=(-2*b+sqrt(panbieshi))/6/a;
max=(-2*b-sqrt(panbieshi))/6/a;
if(f(min,a,b,c,d)>0)
{
do
min=min-1;
while(f(min,a,b,c,d)>=0);
printf("方程有一个不同的实根,为:
%lf",erfenfa(min,max,a,b,c,d));
}
else
if(f(min,a,b,c,d)==0)
{
printf("方程有两个不同的实根,分别为:
\n%lf,",min);
do
min=min-1;
while(f(min,a,b,c,d)>=0);
printf("%lf",erfenfa(min,max,a,b,c,d));
}
else
if(f(max,a,b,c,d)<0)
{
do
max=max+1;
while(f(max,a,b,c,d)<=0);
printf("方程有一个不同的实根,为:
%lf",erfenfa(min,max,a,b,c,d));
}
else
if(f(max,a,b,c,d)==0)
{
printf("方程有两个不同的实根,分别为:
\n%lf,",max);
do
max=max+1;
while(f(max,a,b,c,d)<=0);
printf("%lf",erfenfa(min,max,a,b,c,d));
}
else
{
max1=min;
min1=max;
do
max1=max1+1;
while(f(max1,a,b,c,d)<=0);
do
min1=min1-1;
while(f(min1,a,b,c,d)>=0);
printf("方程有三个不同的实根,分别为:
%lf,%lf,%lf",erfenfa(min1,max,a,b,c,d),erfenfa(max,min,a,b,c,d),erfenfa(min,max1,a,b,c,d));
}
}
else
if(f(0,a,b,c,d)<0)
{
min=0;
max=0;
do
max=max++;
while(f(max,a,b,c,d)<=0);
printf("方程有一个不同的实根,为:
%lf",erfenfa(min,max,a,b,c,d));
}
else
if(f(0,a,b,c,d)>0)
{
max=0;
min=0;
do
min=min-10;
while(f(min,a,b,c,d)>0);
printf("方程有一个不同的实根,为:
%lf",erfenfa(max,min,a,b,c,d));
}
else
printf("方程有一个不同的实根,为:
0");
}
printf("\n");
system("color3");
system("pause");
return0;
}
doublef(doublex,doublea,doubleb,doublec,doubled)
{
doubley;
y=a*x*x*x+b*x*x+c*x+d;
returny;
}
doubleerfenfa(doublem,doublen,doublea,doubleb,doublec,doubled)
{
do
{
if(f((m+n)/2,a,b,c,d)*f(m,a,b,c,d)<0)
{
n=(m+n)/2;
}
else
if(f((m+n)/2,a,b,c,d)*f(m,a,b,c,d)>0)
{
m=(m+n)/2;
}
}while(fabs(f((m+n)/2,a,b,c,d))>=1e-7);
if(fabs((m+n)/2)<1e-6)
{
m=0;
n=0;
}
return(m+n)/2;
}
注:
第40、41行,第55、56行、第63-66行以及第174-178行(倒数第7-倒数第3行)的代码为后期添加,修复了方程的根本应为“0.000000”而概率显示为“-0.000000”的问题。
致谢:
在编写第三个程序时曾遇到诸多问题,感谢余老师发现的问题。
由于我的编程和写作水平有限,所写的程序还可能存在潜在的不足之处以及所写的报告存在一些瑕疵,恳请老师批评和指正!