[C] [vomiting] you have to sort out the C language examples - Go to chapter two commonly used algorithms
table of Contents
Example 84 dichotomy solve the equations
85 Examples of solving equations of Newton iteration method
Solving equations Example 86 Secant Method
Lagrange Interpolation Example 87
Least squares fitting Example 88
Example 89 Simpson numerical integration
Example 91 Runge - Kutta method
Example 92 Gaussian elimination
Example 93 positive definite matrix inversion
Example 84 dichotomy solve the equations
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;
}
}
}
}
run
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 Examples of solving equations of Newton iteration method
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);
}
run
trust100@ubuntu:~/test/clanguage$ ./a.out
利用牛顿跌代法求的的根为:
x=1.4655712319
Solving equations Example 86 Secant Method
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;
}
}
}
}
run
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
Lagrange Interpolation Example 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);
}
run
trust100@ubuntu:~/test/clanguage$ ./a.out
拉各朗日插值后得到的结果是:
f(0.15)=3.944728e-01
Least squares fitting Example 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);
}
run
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
Example 89 Simpson numerical integration
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));
}
run
trust100@ubuntu:~/test/clanguage$ ./a.out
利用定步长辛普生积分结果为:
I1 = 0.7173564899
利用变步长辛普生积分结果为:
I2 = 7.173566e-01
Example 90 Improved Euler
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");
}
}
run
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
Example 91 Runge - Kutta method
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;
}
run
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
Example 92 Gaussian elimination
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);
}
run
trust100@ubuntu:~/test/clanguage$ ./a.out
该方程组的解为:
x0 = 3.00
x1 = -2.00
x2 = 6.00
Example 93 positive definite matrix inversion
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);
}
run
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