【C】【吐血整理】你们要的C语言实例大全-常用算法篇二

【C】【吐血整理】你们要的C语言实例大全-常用算法篇二

目录

 

实例84 二分法求解方程

实例85 牛顿迭代法求解方程

实例86 弦截法求解方程

实例87 拉格朗日插值

实例88 最小二乘法拟合

实例89 辛普生数值积分

实例90 改进欧拉法

实例91 龙格-库塔法

实例92 高斯消去法

实例93 正定矩阵求逆


实例84 二分法求解方程

bisectroot.c

#include <stdio.h>
#include <math.h>
#include <malloc.h>
#include <stdlib.h>

double Func(double);
int BisectRoot(double,double,double,double,double *,int,int *);

void main()
{
	int i,n,m;
	double a,b,h,eps,*x;
	n = 3;						/*方程根的个数的预估值*/
	x = (double*)calloc(n,sizeof(double));		/*开辟内存空间*/
	if(x == NULL)
	{
		printf("内存分配失败\n");
		exit(1);
	}
	a = -3;								/*区间起始端点*/
	b = 7;								/*区间终止端点*/
	h = 0.1;							/*步长*/
	eps = 1.e-8;						/*要求达到的精度*/
	BisectRoot(a,b,h,eps,x,n,&m);		/*调用二分法函数*/
	printf("y=sin(x)在范围%2.0f和%2.0f之间的根有%d个根\n",a,b,m);
	printf("它们分别是:\n");
	for(i = 0;i<n;i++)
	printf("x[%d] = %e\n",i,x[i]);
	free(x);					/*释放内存空间*/
}

double Func(double x)
{
	return(sin(x));
}

int BisectRoot(a,b,h,eps,x,n,m)
double a;			/*实型变量,输入参数,求根区间的起始端点*/
double b;			/*实型变量,输入参数,求根区间的终止端点*/
double h;			/*利用逐步扫描法确定根位置时的步长*/
double eps;			/*实型变量,输入参数,控制精度的参数*/
double *x;			/*实型一维数组,输出参数,存放计算得到的数组*/
int n;				/*输入参数,区间内方程根的个数的预估值*/
int *m;				/*输出参数,实际求得的根的个数*/
{
	double z,z0,z1,y,y0,y1;
	*m = 0;
	z = a;
	y = Func(z);
	while(1)		/*无限循环,直到遇到return或者break语句*/
	{/*如果逐步扫描到求根区间的右端点或者得到的根的个数达到预估根的个数*/
		if((z>b+h/2)||(*m==n))	
			return(1);
		if(fabs(y)<eps)		/*如果当前根z对应的函数f(z)满足精度要求*/
		{
			*m+=1;
			x[*m-1] = z;	/*将此时的z值赋值给x数组*/
			z+=h/2;
			y = Func(z);
			continue;		/*结束本次循环,即跳过循环体中下面尚未执行
							 的语句接着进行下一次是否执行循环的判定*/
		}
	
		z1 = z+h;			/*逐步扫描中小区间的右端点*/
		y1 = Func(z1);		/*小区间右端点对应的函数值*/
		if(fabs(y1)<eps)	/*如果右端点恰好满足根的精度要求*/
		{
			*m+=1;
			x[*m-1] = z1;
			z = z1+h/2;
			y = Func(z);
			continue;
		}
		if(y*y1>0)			/*如果对应根乘积大于零,说明该区间内没有根*/
		{
			y = y1;			
			z = z1;
			continue;
		}
		while(1)		/*如果本while循环执行,说明逐步扫描小区建z和z1间有根*/
		{
			if(fabs(z1-z)<eps)		/*如果满足精度要求*/
			{
				*m+=1;
				x[*m-1]=(z1+z)/2;
				z = z1+h/2;
				y = Func(z);
				break;
			}
			z0 = (z1+z)/2;			/*二分发求根公式*/
			y0 = Func(z0);
			if(fabs(y0)<eps)
			{
				*m = *m+1;
				x[*m-1] = z0;
				z =z0+h/2;
				y = Func(z);
				break;
			}
			if(y*y0<0)			/*如果乘积小于零,说明根在z和z0之间*/
			{
				z1 = z0;
				y1 = y0;
			}
			else				/*否则根在z0和z1之间*/
			{
				z = z0;
				y = y0;
			}
		}
	}
}


运行

trust100@ubuntu:~/test/clanguage$ ./a.out 
y=sin(x)在范围-3和 7之间的根有3个根
它们分别是:
x[0] = 1.526557e-15
x[1] = 3.141593e+00
x[2] = 6.283185e+00


实例85 牛顿迭代法求解方程

Newton.c

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int Function(double,double *,double *);
int Newton(double *,double,int);

int Function(x,f,dy)
double x;
double *f;
double *dy;
{
	*f = x*x*(x-1)-1;
	*dy = 3*x*x-2*x;
	return(1);
}

int Newton(x,eps,l)
double *x;
double eps;
int l;
{
	double f,dy,x1;
	Function(*x,&f,&dy);
A:	if(fabs(dy) == 0)
	{
		l = 0;
		return (0);
	}
	x1=*x-f/dy;
	Function(x1,&f,&dy);
	if(fabs(x1-*x)>=eps||fabs(f)>=eps)
	{
		l-=1;
		*x=x1;
		if(l==0)
			return(1);
		goto A;
	}
	*x = x1;
	return 1;
}

void main()
{
	double x,eps;
	int l;
	eps=1.e-6;
	x=1.5;
	l=60;
	if(!Newton(&x,eps,l))
	{
		printf("该函数不可以用牛顿跌代法求根!\n");
	}
	printf("利用牛顿跌代法求的的根为:\n");
	printf("x=%.10f\n",x);
}

运行

trust100@ubuntu:~/test/clanguage$ ./a.out 
利用牛顿跌代法求的的根为:
x=1.4655712319


实例86 弦截法求解方程

BowRoot.c

#include <stdio.h>
#include <math.h>
#include <malloc.h>
#include <stdlib.h>

double Func(double);
int BowRoot(double,double,double,double,double *,int,int *);

void main()
{
	int i,n,m;
	double a,b,h,eps,*x;
	n = 3;						/*方程根的个数的预估值*/
	x = (double*)calloc(n,sizeof(double));		/*开辟内存空间*/
	if(x == NULL)
	{
		printf("内存分配失败\n");
		exit(1);
	}
	a = -3;								/*区间起始端点*/
	b = 5;								/*区间终止端点*/
	h = 1;								/*步长*/
	eps = 1.e-8;						/*要求达到的精度*/
	BowRoot(a,b,h,eps,x,n,&m);		/*调用二分法函数*/
	printf("函数f(x)在范围%2.0f和%2.0f之间的根有%d个根\n",a,b,m);
	printf("它们分别是:\n");
	for(i = 0;i<n;i++)
	printf("x[%d] = %e\n",i,x[i]);
	free(x);					/*释放内存空间*/
}

double Func(double x)
{
	return (x*x*x-3*x*x-6*x+8);
}

int BowRoot(a,b,h,eps,x,n,m)
double a;			/*实型变量,输入参数,求根区间的起始端点*/
double b;			/*实型变量,输入参数,求根区间的终止端点*/
double h;			/*利用逐步扫描法确定根位置时的步长*/
double eps;			/*实型变量,输入参数,控制精度的参数*/
double *x;			/*实型一维数组,输出参数,存放计算得到的数组*/
int n;				/*输入参数,区间内方程根的个数的预估值*/
int *m;				/*输出参数,实际求得的根的个数*/
{
	double z,z1,z2,y,y1,y2;
	*m = 0;
	z = a;
	y = Func(z);
	while(1)		/*无限循环,直到遇到return或者break语句*/
	{/*如果逐步扫描到求根区间的右端点或者得到的根的个数达到预估根的个数*/
		if((z>b+h/2)||(*m==n))	
			return(1);
		if(fabs(y)<eps)		/*如果当前根z对应的函数f(z)满足精度要求*/
		{
			*m+=1;
			x[*m-1] = z;	/*将此时的z值赋值给x数组*/
			z+=h/2;
			y = Func(z);
			continue;		/*结束本次循环,即跳过循环体中下面尚未执行
							 的语句接着进行下一次是否执行循环的判定*/
		}
	
		z1 = z+h;			/*逐步扫描中小区间的右端点*/
		y1 = Func(z1);		/*小区间右端点对应的函数值*/
		if(fabs(y1)<eps)	/*如果右端点恰好满足根的精度要求*/
		{
			*m+=1;
			x[*m-1] = z1;
			z = z1+h/2;
			y = Func(z);
			continue;
		}
		if(y*y1>0)			/*如果对应根乘积大于零,说明该区间内没有根*/
		{
			y = y1;			
			z = z1;
			continue;
		}
		while(1)		/*如果本while循环执行,说明逐步扫描小区建z和z1间有根*/
		{
			if(fabs(z1-z)<eps)		/*如果满足精度要求*/
			{
				*m+=1;
				x[*m-1]=(z1+z)/2;
				z = z1+h/2;
				y = Func(z);
				break;
			}

			y1 = Func(z1);				/*弦截法公式*/
			y = Func(z);
			z2=z1-(y1/(y1-y))*(z1-z);
			y2 = Func(z2);

			if(fabs(y2)<eps)
			{
				*m = *m+1;
				x[*m-1] = z2;
				z =z2+h/2;
				y = Func(z);
				break;
			}
			if(y*y2<0)			/*如果乘积小于零,说明根在z和z0之间*/
			{
				z1 = z2;
				y1 = y2;
			}
			else				/*否则根在z0和z1之间*/
			{
				z = z2;
				y = y2;
			}
		}
	}
}


运行

trust100@ubuntu:~/test/clanguage$ ./a.out 
函数f(x)在范围-3和 5之间的根有3个根
它们分别是:
x[0] = -2.000000e+00
x[1] = 1.000000e+00
x[2] = 4.000000e+00


实例87 拉格朗日插值

Lagrange.c

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

double LAG(int,double *,double *,double);

void main()
{
	int n;
	double *x,*y,t,lag;
	t = 0.15;
	n = 6;
	x = (double*)calloc(n,sizeof(double));
	if(x == NULL)
	{
		printf("内存分配失败\n");
		exit(1);
	}
	y = (double*)calloc(n,sizeof(double));
	if(y == NULL)
	{
		printf("内存分配失败\n");
		exit(1);
	}
	x[0] = 0;
	x[1] = 0.1;
	x[2] = 0.195;
	x[3] = 0.3;
	x[4] = 0.401;
	x[5] = 0.5;

	y[0] = 0.39894;
	y[1] = 0.39695;
	y[2] = 0.39142;
	y[3] = 0.38138;
	y[4] = 0.36812;
	y[5] = 0.35206;

	lag = LAG(n,x,y,t);
	printf("拉各朗日插值后得到的结果是:\n");
	printf("f(%.2f)=%e\n",t,lag);
	free(x);
	free(y);
}

double LAG(n,x,y,t)
int n;
double *x;
double *y;
double t;
{
	int i,j;
	double p,s;
	s = 0;
	for(i=0;i<n-1;i++)
	{
		p = 1;
		for(j=0;j<n-1;j++)
			if(i!=j)
				p*=(t-x[j])/(x[i]-x[j]);
			s+=p*y[i];
	}
	return (s);
}

运行

trust100@ubuntu:~/test/clanguage$ ./a.out 
拉各朗日插值后得到的结果是:
f(0.15)=3.944728e-01


实例88 最小二乘法拟合

smooth.c

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>

Smooth(double *,double *,double *,int,int,
	   double *,double *,double *);
void main()
{
	int i,n,m;
	double *x,*y,*a,dt1,dt2,dt3,b;
	n = 20;
	m = 6;
	b = 0;
	/*分别为x,y,a分配存贮空间*/
	x = (double *)calloc(n,sizeof(double));
	if(x == NULL)
	{
		printf("内存分配失败\n");
		exit (0);
	}
	y = (double *)calloc(n,sizeof(double));
	if(y == NULL)
	{
		printf("内存分配失败\n");
		exit (0);
	}
	a = (double *)calloc(n,sizeof(double));
	if(a == NULL)
	{
		printf("内存分配失败\n");
		exit (0);
	}
	for(i=1;i<=n;i++)
	{
		x[i-1]=b+(i-1)*0.1;
		/*每隔0.1取一个点,这样连续取n个点*/
		y[i-1]=x[i-1]-exp(-x[i-1]);
		/*计算x[i-1]点对应的y值作为拟合已知值*/
	}
	Smooth(x,y,a,n,m,&dt1,&dt2,&dt3);			/*调用拟合函数*/
	for(i=1;i<=m;i++)
		printf("a[%d] = %.10f\n",(i-1),a[i-1]);
	printf("拟合多项式与数据点偏差的平方和为:\n");
	printf("%.10e\n",dt1);
	printf("拟合多项式与数据点偏差的绝对值之和为:\n");
	printf("%.10e\n",dt2);
	printf("拟合多项式与数据点偏差的绝对值最大值为:\n");
	printf("%.10e\n",dt3);
	free(x);								/*释放存储空间*/
	free(y);								/*释放存储空间*/
	free(a);								/*释放存储空间*/
}

	Smooth(x,y,a,n,m,dt1,dt2,dt3 )
		double *x;				/*实型一维数组,输入参数,存放节点的xi值*/
		double *y;				/*实型一维数组,输入参数,存放节点的yi值*/
		double *a;				/*双精度实型一维数组,长度为m。返回m一1次拟合多项式的m个系数*/
		int n;					/*整型变量,输入参数,给定数据点的个数*/
		int m;					/*整型变量,输入参数,拟合多项式的项数*/
		double *dt1;			/*实型变量,输出参数,拟合多项式与数据点偏差的平方和*/
		double *dt2;			/*实型变量,输出参数,拟合多项式与数据点偏差的绝对值之和*/
		double *dt3;			/*实型变量,输出参数,拟合多项式与数据点偏差的绝对值最大值*/
	{
		int i,j,k;
		double *s,*t,*b,z,d1,p,c,d2,g,q,dt;
		/*分别为s,t,b分配存贮空间*/
		s = (double *)calloc(n,sizeof(double));
		if(s == NULL)
		{
			printf("内存分配失败\n");
			exit (0);
		}
		t = (double *)calloc(n,sizeof(double));
		if(t == NULL)
		{
			printf("内存分配失败\n");
			exit (0);
		}
		b = (double *)calloc(n,sizeof(double));
		if(b == NULL)
		{
			printf("内存分配失败\n");
			exit (0);
		}
		z = 0;
		for(i=1;i<=n;i++)
			z=z+x[i-1]/n;			/*z为各个x的平均值*/
		b[0]=1;
		d1=n;
		p=0;
		c=0;
		for(i=1;i<=n;i++)
		{
			p=p+x[i-1]-z;
			c=c+y[i-1];
		}
		c=c/d1;
		p=p/d1;
		a[0]=c*b[0];
		if(m>1)
		{
			t[1]=1;
			t[0]=-p;
			d2=0;
			c=0;
			g=0;
			for(i=1;i<=n;i++)
			{
				q=x[i-1]-z-p;
				d2=d2+q*q;
				c=y[i-1]*q+c;
				g=(x[i-1]-z)*q*q+g;
			}
			c=c/d2;
			p=g/d2;
			q=d2/d1;
			d1=d2;
			a[1]=c*t[1];
			a[0]=c*t[0]+a[0];
		}
		for(j=3;j<=m;j++)
		{
			s[j-1]=t[j-2];
			s[j-2]=-p*t[j-2]+t[j-3];
			if(j>=4)
				for(k=j-2;k>=2;k--)
					s[k-1]=-p*t[k-1]+t[k-2]-q*b[k-1];
				s[0]=-p*t[0]-q*b[0];
				d2=0;
				c=0;
				g=0;
				for(i=1;i<=n;i++)
				{
					q=s[j-1];
					for(k=j-1;k>=1;k--)
						q=q*(x[i-1]-z)+s[k-1];
					d2=d2+q*q;
					c=y[i-1]*q+c;
					g=(x[i-1]-z)*q*q+g;
				}
				c=c/d2;
				p=g/d2;
				q=d2/d1;
				d1=d2;
				a[j-1]=c*s[j-1];
				t[j-1]=s[j-1];
				for(k=j-1;k>=1;k--)
				{
					a[k-1]=c*s[k-1]+a[k-1];
					b[k-1]=t[k-1];
					t[k-1]=s[k-1];
				}
		}
		*dt1=0;
		*dt2=0;
		*dt3=0;
		for(i=1;i<=n;i++)
		{
			q=a[m-1];
			for(k=m-1;k>=1;k--)
				q=q*(x[i-1]-z)+a[k-1];
			dt=q-y[i-1];
			if(fabs(dt)>*dt3)
				*dt3=fabs(dt);
			*dt1=*dt1+dt*dt;
			*dt2=*dt2+fabs(dt);
		}
		/*释放存储空间*/
		free(s);
		free(t);
		free(b);
		return(1);
	}

运行

trust100@ubuntu:~/test/clanguage$ ./a.out 
a[0] = 0.5632480493
a[1] = 1.3867467012
a[2] = -0.1931338887
a[3] = 0.0644035495
a[4] = -0.0168412204
a[5] = 0.0033442883
拟合多项式与数据点偏差的平方和为:
1.8017419171e-09
拟合多项式与数据点偏差的绝对值之和为:
1.6850492746e-04
拟合多项式与数据点偏差的绝对值最大值为:
1.5393962046e-05


实例89 辛普生数值积分

simp.c

#include <stdio.h>
#include <math.h>

double Function(double);
double SIMP1(double,double,int);
double SIMP2(double,double,double);

void main()
{
	double a1,b1,eps;
	int n1;
	double Result1;
	double Result2;
	a1 = 0.0;
	b1 = 0.8;
	n1 = 4;
	eps = 5e-7;
	Result1 = SIMP1(a1,b1,n1);
	Result2 = SIMP2(a1,b1,eps);
	printf("利用定步长辛普生积分结果为:\n");
	printf("I1 = %.10f\n",Result1);
	printf("利用变步长辛普生积分结果为:\n");
	printf("I2 = %e\n",Result2);
}

double SIMP1(a,b,n)
double a;
double b;
int n;
{
	int i;
	double h,s;
	h=(a-b)/(2*n);
	s=0.5*(Function(a)-Function(b));
	for(i=1;i<=n;i++)
		s+=2*Function(a+(2*i-1)*h)+Function(a+2*i*h);
	return((b-a)*s/(3*n));
}

double SIMP2(a,b,eps)
double a;
double b;
double eps;
{
	int k,n;
	double h,t1,t2,s1,s2,p,x;
	n=1;
	h=b-a;
	t1=h*(Function(a)+Function(b))/2;
	s1 = t1;
	while(1)
	{
		p = 0;
		for(k=0;k<=n;k++)
		{
			x = a+(k+0.5)*h;
			p+=Function(x);
		}
		t2=(t1+h*p)/2;
		s2=(4*t2-t1)/3;
		if(fabs(s2-s1)>=eps)
		{
			t1=t2;
			n=n+n;
			h=h/2;
			s1=s2;
			continue;
		}
		break;
	}
	return(s2);
}

double Function(double x)
{
	return(cos(x));
}

运行

trust100@ubuntu:~/test/clanguage$ ./a.out 
利用定步长辛普生积分结果为:
I1 = 0.7173564899
利用变步长辛普生积分结果为:
I2 = 7.173566e-01


实例90 改进欧拉法

Euler.C


#include "stdio.h"
#include "stdlib.h"
#include <math.h>

int Func(y,d)
double y[],d[];
{
	d[0]=y[1];		/*y0'=y1*/
	d[1]=-y[0];		/*y1'=y0*/
	d[2]=-y[2];		/*y2'=y2*/
	return(1);
}

void Euler1(t,y,n,h,k,z)
int n;		/*整型变量,微分方程组中方程的个数,也是未知函数的个数*/
int k;		/*整型变量。积分步数(包括起始点这一步)*/
double t;		/*双精度实型变量,对微分方程进行积分的起始点t0*/
double h;		/*双精度实型变量。积分步长*/
double y[];	/*双精度实型一维数组,长度为n。存放n个未知函数yi在起始点t0处的函数值*/
double z[];	/*双精度实型二维数组,体积为nxk。返回k个积分点(包括起始点)上的未知函数值*/
{ 
	extern int Func();
	int i,j;
	double *d;
	d=malloc(n*sizeof(double));
	if(d == NULL)
	{
		printf("内存分配失败\n");
		exit(1);
	}
	/*将方程组的初值赋给数组z[i*k]*/
	for (i=0; i<=n-1; i++)
		z[i*k]=y[i];
	for (j=1; j<=k-1; j++)
	{
		Func(y,d);			/*求出f(x)*/
		for(i=0; i<=n-1; i++)
			y[i]=z[i*k+j-1]+h*d[i];

		Func(y,d);
		for (i=0; i<=n-1; i++)
			d[i]=z[i*k+j-1]+h*d[i];
		for (i=0; i<=n-1; i++)
		{
			y[i]=(y[i]+d[i])/2.0;
			z[i*k+j]=y[i];
		}
	}
    free(d); 
	return;
  }
void Euler2(t,h,y,n,eps)
int n;
double t,h,eps,y[];
{
	int i,j,m;
	double hh,p,q,*a,*b,*c,*d;
    a=malloc(n*sizeof(double));
    b=malloc(n*sizeof(double));
    c=malloc(n*sizeof(double));
    d=malloc(n*sizeof(double));
    hh=h;
	m=1; 
	p=1.0+eps;
	for (i=0; i<=n-1; i++) a[i]=y[i];
    while (p>=eps)
    {
		for (i=0; i<=n-1; i++)
        {
			b[i]=y[i];
			y[i]=a[i];
		}
        for (j=0; j<=m-1; j++)
        {
			for (i=0; i<=n-1; i++) 
				c[i]=y[i];
            Func(y,d);
            for (i=0; i<=n-1; i++)
                y[i]=c[i]+hh*d[i];
            Func(y,d);
            for (i=0; i<=n-1; i++)
                d[i]=c[i]+hh*d[i];
            for (i=0; i<=n-1; i++)
                y[i]=(y[i]+d[i])/2.0;
        }
        p=0.0;
        for (i=0; i<=n-1; i++)
        {
			q=fabs(y[i]-b[i]);
            if (q>p) p=q;
        }
        hh=hh/2.0; m=m+m;
	}
    free(a); 
	free(b); 
	free(c);
	free(d);
	return;
}
main()
{
	int i,j;
	double y[3],z[3][11],t,h,x,eps;
	y[0]=-1.0;			/*初值y0(0)=-1.0*/
	y[1]=0.0;			/*初值y1(0)=-1.0*/
	y[2]=1.0;			/*初值y2(0)=-1.0*/
	t=0.0;				/*起始点t=0*/
	h=0.01;				/*步长为0.01*/
	eps = 0.00001;
	Euler1(t,y,3,h,11,z);
	printf("定步长欧拉法结果:\n");
	for (i=0; i<=10; i++)
	{
		x=i*h;
		printf("t=%5.2f\t   ",x);
		for(j=0; j<=2; j++)
			printf("y(%d)=%e  ",j,z[j][i]);
		printf("\n");
	}
	y[0]=-1.0;			/*重新赋初值*/
	y[1]=0.0;			
	y[2]=1.0;			
	printf("变步长欧拉法结果:\n");
	printf("t=%5.2f\t   ",t);
	for (i=0; i<=2; i++)
		printf("y(%d)=%e  ",i,y[i]);
	printf("\n");
	for (j=1; j<=10; j++)
	{
		Euler2(t,h,y,3,eps);
		t=t+h;
		printf("t=%5.2f\t   ",t);
		for (i=0; i<=2; i++)
			printf("y(%d)=%e  ",i,y[i]);
		printf("\n");
	}
}

运行

trust100@ubuntu:~/test/clanguage$ ./a.out 
定步长欧拉法结果:
t= 0.00	   y(0)=-1.000000e+00  y(1)=0.000000e+00  y(2)=1.000000e+00  
t= 0.01	   y(0)=-9.999500e-01  y(1)=1.000000e-02  y(2)=9.900500e-01  
t= 0.02	   y(0)=-9.998000e-01  y(1)=1.999900e-02  y(2)=9.801990e-01  
t= 0.03	   y(0)=-9.995500e-01  y(1)=2.999600e-02  y(2)=9.704460e-01  
t= 0.04	   y(0)=-9.992001e-01  y(1)=3.999000e-02  y(2)=9.607901e-01  
t= 0.05	   y(0)=-9.987502e-01  y(1)=4.998000e-02  y(2)=9.512302e-01  
t= 0.06	   y(0)=-9.982005e-01  y(1)=5.996501e-02  y(2)=9.417655e-01  
t= 0.07	   y(0)=-9.975509e-01  y(1)=6.994401e-02  y(2)=9.323949e-01  
t= 0.08	   y(0)=-9.968016e-01  y(1)=7.991602e-02  y(2)=9.231176e-01  
t= 0.09	   y(0)=-9.959526e-01  y(1)=8.988004e-02  y(2)=9.139326e-01  
t= 0.10	   y(0)=-9.950040e-01  y(1)=9.983508e-02  y(2)=9.048389e-01  
变步长欧拉法结果:
t= 0.00	   y(0)=-1.000000e+00  y(1)=0.000000e+00  y(2)=1.000000e+00  
t= 0.01	   y(0)=-9.999500e-01  y(1)=9.999875e-03  y(2)=9.900499e-01  
t= 0.02	   y(0)=-9.998000e-01  y(1)=1.999875e-02  y(2)=9.801988e-01  
t= 0.03	   y(0)=-9.995500e-01  y(1)=2.999563e-02  y(2)=9.704457e-01  
t= 0.04	   y(0)=-9.992001e-01  y(1)=3.998950e-02  y(2)=9.607896e-01  
t= 0.05	   y(0)=-9.987503e-01  y(1)=4.997938e-02  y(2)=9.512296e-01  
t= 0.06	   y(0)=-9.982005e-01  y(1)=5.996426e-02  y(2)=9.417648e-01  
t= 0.07	   y(0)=-9.975510e-01  y(1)=6.994314e-02  y(2)=9.323941e-01  
t= 0.08	   y(0)=-9.968017e-01  y(1)=7.991503e-02  y(2)=9.231167e-01  
t= 0.09	   y(0)=-9.959527e-01  y(1)=8.987892e-02  y(2)=9.139315e-01  
t= 0.10	   y(0)=-9.950041e-01  y(1)=9.983383e-02  y(2)=9.048378e-01 


实例91 龙格-库塔法

GRKT10.C


#include "stdio.h"
#include "stdlib.h"

void RKT(t,y,n,h,k,z)
int n;				/*微分方程组中方程的个数,也是未知函数的个数*/
int k;				/*积分的步数(包括起始点这一步)*/
double t;			/*积分的起始点t0*/
double h;			/*积分的步长*/
double y[];			/*存放n个未知函数在起始点t处的函数值,返回时,其初值在二维数组z的第零列中*/
double z[];			/*二维数组,体积为n x k.返回k个积分点上的n个未知函数值*/
{
	extern void Func();				/*声明要求解的微分方程组*/
    int i,j,l;
    double a[4],*b,*d;
    b=malloc(n*sizeof(double));		/*分配存储空间*/
	if(b == NULL)
	{
		printf("内存分配失败\n");
		exit(1);
	}
    d=malloc(n*sizeof(double));		/*分配存储空间*/
	if(d == NULL)
	{
		printf("内存分配失败\n");
		exit(1);
	}
	/*后面应用RK4公式中用到的系数*/
    a[0]=h/2.0;						
	a[1]=h/2.0;
    a[2]=h; 
	a[3]=h;
    for(i=0; i<=n-1; i++) 
		z[i*k]=y[i];				/*将初值赋给数组z的相应位置*/
    for(l=1; l<=k-1; l++)
    {
		Func(y,d);
        for (i=0; i<=n-1; i++)
			b[i]=y[i];
        for (j=0; j<=2; j++)
        {
			for (i=0; i<=n-1; i++)
            {
				y[i]=z[i*k+l-1]+a[j]*d[i];
                b[i]=b[i]+a[j+1]*d[i]/3.0;
            }
            Func(y,d);
        }
        for(i=0; i<=n-1; i++)
          y[i]=b[i]+h*d[i]/6.0;
        for(i=0; i<=n-1; i++)
          z[i*k+l]=y[i];
        t=t+h;
	}
    free(b);			/*释放存储空间*/
	free(d);			/*释放存储空间*/
    return;
}
main()
{
	int i,j;
    double t,h,y[3],z[3][11];
    y[0]=-1.0; 
	y[1]=0.0; 
	y[2]=1.0;
    t=0.0; 
	h=0.01;
    RKT(t,y,3,h,11,z);
    printf("\n");
    for (i=0; i<=10; i++)			/*打印输出结果*/
    {
		t=i*h;
        printf("t=%5.2f\t   ",t);
        for (j=0; j<=2; j++)
          printf("y(%d)=%e  ",j,z[j][i]);
        printf("\n");
	}
}

void Func(y,d)
double y[],d[];
{
	d[0]=y[1];		/*y0'=y1*/
	d[1]=-y[0];		/*y1'=y0*/
	d[2]=-y[2];		/*y2'=y2*/
	return;
}


运行

trust100@ubuntu:~/test/clanguage$ ./a.out 

t= 0.00	   y(0)=-1.000000e+00  y(1)=0.000000e+00  y(2)=1.000000e+00  
t= 0.01	   y(0)=-9.999500e-01  y(1)=9.999833e-03  y(2)=9.900498e-01  
t= 0.02	   y(0)=-9.998000e-01  y(1)=1.999867e-02  y(2)=9.801987e-01  
t= 0.03	   y(0)=-9.995500e-01  y(1)=2.999550e-02  y(2)=9.704455e-01  
t= 0.04	   y(0)=-9.992001e-01  y(1)=3.998933e-02  y(2)=9.607894e-01  
t= 0.05	   y(0)=-9.987503e-01  y(1)=4.997917e-02  y(2)=9.512294e-01  
t= 0.06	   y(0)=-9.982005e-01  y(1)=5.996401e-02  y(2)=9.417645e-01  
t= 0.07	   y(0)=-9.975510e-01  y(1)=6.994285e-02  y(2)=9.323938e-01  
t= 0.08	   y(0)=-9.968017e-01  y(1)=7.991469e-02  y(2)=9.231163e-01  
t= 0.09	   y(0)=-9.959527e-01  y(1)=8.987855e-02  y(2)=9.139312e-01  
t= 0.10	   y(0)=-9.950042e-01  y(1)=9.983342e-02  y(2)=9.048374e-01  


实例92 高斯消去法

gs.c

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>

int GS(int,double**,double *,double);
double **TwoArrayAlloc(int,int);
void TwoArrayFree(double **);

void main()
{
	int i,n;
	double ep,**a,*b;
	n = 3;
	ep = 1e-4;
	a = TwoArrayAlloc(n,n);
	b = (double *)calloc(n,sizeof(double));
	if(b == NULL)
	{
		printf("内存分配失败\n");
		exit(1);
	}
	a[0][0]= 2; a[0][1]= 6; a[0][2]=-1;
	a[1][0]= 5; a[1][1]=-1; a[1][2]= 2;
	a[2][0]=-3; a[2][1]=-4; a[2][2]= 1;
	b[0] = -12; b[1] = 29;  b[2] = 5;
	if(!GS(n,a,b,ep))
	{
		printf("不可以用高斯消去法求解\n");
		exit(0);
	}
	printf("该方程组的解为:\n");
	for(i=0;i<3;i++)
		printf("x%d = %.2f\n",i,b[i]);
	TwoArrayFree(a);
	free(b);
}

int GS(n,a,b,ep)
int n;
double **a;
double *b;
double ep;
{
	int i,j,k,l;
	double t;
	for(k=1;k<=n;k++)
	{
		for(l=k;l<=n;l++)
			if(fabs(a[l-1][k-1])>ep)
				break;
			else if(l==n)
				return(0);
		if(l!=k)
		{
			for(j=k;j<=n;j++)
			{
				t = a[k-1][j-1];
				a[k-1][j-1]=a[l-1][j-1];
				a[l-1][j-1]=t;
			}
			t=b[k-1];
			b[k-1]=b[l-1];
			b[l-1]=t;
		}
		t=1/a[k-1][k-1];
		for(j=k+1;j<=n;j++)
			a[k-1][j-1]=t*a[k-1][j-1];
		b[k-1]*=t;
		for(i=k+1;i<=n;i++)
		{
			for(j=k+1;j<=n;j++)
				a[i-1][j-1]-=a[i-1][k-1]*a[k-1][j-1];
			b[i-1]-=a[i-1][k-1]*b[k-1];
		}
	}
	for(i=n-1;i>=1;i--)
		for(j=i+1;j<=n;j++)
			b[i-1]-=a[i-1][j-1]*b[j-1];
return(1);
}

double **TwoArrayAlloc(int r,int c)
{
	double *x,**y;
	int n;
	x=(double *)calloc(r*c,sizeof(double));
	y=(double **)calloc(r,sizeof(double*));
	for(n=0;n<=r-1;++n)
		y[n]=&x[c*n];
	return (y);
}

void TwoArrayFree(double **x)
{
	free(x[0]);
	free(x);
}

运行

trust100@ubuntu:~/test/clanguage$ ./a.out 
该方程组的解为:
x0 = 3.00
x1 = -2.00
x2 = 6.00


实例93 正定矩阵求逆

gj.c

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

int GJ(int,double **);
double **TwoArrayAlloc(int,int);
void TwoArrayFree(double **);

void main()
{
	int i,j,n;
	double **a;
	n=4;
	a=TwoArrayAlloc(n,n);

	a[0][0]=5;	a[0][1]=7;	a[0][2]=6;	a[0][3]=5;
	a[1][0]=7;	a[1][1]=10;	a[1][2]=8;	a[1][3]=7;
	a[2][0]=6;	a[2][1]=8;	a[2][2]=10;	a[2][3]=9;
	a[3][0]=5;	a[3][1]=7;	a[3][2]=9;	a[3][3]=10;
	if(!GJ(n,a))
	{
		printf("矩阵求逆失败\n");
		exit(1);
	}
	printf("该矩阵的逆为:\n");
	for(i=0;i<n;i++)
	{
		for(j=0;j<n;j++)
			printf("%.2f\t",a[i][j]);
		printf("\n");
	}
}

int GJ(int n,double **a)
{
	int i,j,k;
	double p,q,*h;
	h=(double *)calloc(n,sizeof(double));
	if(h == NULL)
	{
		printf("内存分配失败\n");
		exit(1);
	}
	for(k=n;k>=1;k--)
	{
		p=a[0][0];
		if(p<=0)
		{
			free(h);
			return (0);
		}
		for(i=2;i<=n;i++)
		{
			q=a[i-1][0];
			if(i>k)
				h[i-1]=q/p;
			else
				h[i-1]=-q/p;
			for(j=2;j<=i;j++)
				a[i-2][j-2]=a[i-1][j-1]+q*h[j-1];
		}
		a[n-1][n-1]=1/p;
		for(i=2;i<=n;i++)
			a[n-1][i-2]=h[i-1];
	}
	free(h);
	return(1);
}

double **TwoArrayAlloc(int r,int c)
{
	double *x,**y;
	int n;
	x=(double *)calloc(r*c,sizeof(double));
	y=(double **)calloc(r,sizeof(double*));
	for(n=0;n<=r-1;++n)
		y[n]=&x[c*n];
	return (y);
}

void TwoArrayFree(double **x)
{
	free(x[0]);
	free(x);
}

运行

trust100@ubuntu:~/test/clanguage$ ./a.out 
该矩阵的逆为:
68.00	7.00	6.00	5.00	
-41.00	25.00	8.00	7.00	
-17.00	10.00	5.00	9.00	
10.00	-6.00	-3.00	2.00	
发布了201 篇原创文章 · 获赞 46 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/rong11417/article/details/104755172