#include <stdio.h> #include <math.h> #include <iostream> #define PrecisionLevel 1.0e-12 //迭代精度 double Z[6][6];//将Z声明为全局变量,便于后面操作 double** CreateMatrix(int m,int n); void DestroyMatrix(double**A,int m,int n); bool GaussElimination(double **A,int n,double* b); double InfiniteNorm(double*b,int n); void CoefficientMatrix(double* x,int m,double* y,int n,double** z,int k1,int k2,double** C); double P_Value(double **C,int k,double x,double y); double** SurfaceFitting(int& k); //----------------------------------------------- //生成一个m*n矩阵 double** CreateMatrix(int m,int n) { double** A; int i; A=new double* [m]; for(i=0;i<m;i++) A[i]=new double[n]; return A; } //----------------------------------------------- //释放m*n矩阵 void DestroyMatrix(double** A,int m,int n) { int i; for(i=0; i<m; i++) delete[]A[i]; delete[]A; } //----------------------------------------------- //列主元Guass削去法求解线性方程组,A*x=b bool GaussElimination(double** A,int n,double* b) { double m,sum,max,temp; int i,j,k,l; for(i=0; i<n-1; i++) { max=A[i][i]; l=i; for(j=i; j<n; j++) //寻找列主元 if(fabs(A[i][j])>max) { max=fabs(A[i][j]); l=j; } if(l!=i) //判断并换行 { for(j=i; j<n; j++) { temp=A[i][j]; A[i][j]=A[l][j]; A[l][j]=temp; } temp=b[i]; b[i]=b[l]; b[l]=temp; } if(A[i][i]==0) { printf("第%d个主元素为0!\n",i); return false; } for(j=i+1; j<n; j++) //消元 { m=A[j][i]/A[i][i]; for(k=i+1;k<n;k++) A[j][k]=A[j][k]-A[i][k]*m; b[j]=b[j]-b[i]*m; } } if(A[n-1][n-1]==0) { printf("第%d个主元素为0!\n",n); return false; } //回带求解,用b来存储解x b[n-1]=b[n-1]/A[n-1][n-1]; for(i=n-2; i>=0; i--) { sum=0; for(j=i+1; j<n; j++) sum+=A[i][j]*b[j]; b[i]=(b[i]-sum)/A[i][i]; } return true; } //----------------------------------------------- //计算向量的无穷范数 double InfiniteNorm(double* b,int n) { double max; int i; max=b[0]; for(i=1; i<n; i++) { if(fabs(b[i])>max) max=fabs(b[i]); } return max; } //----------------------------------------------- //分片二次代数插值,z=z(u,t) double PiecewiseInterpolation(double t,double u) { double pnm=0.0; int i,j; bool flag=false; //判断t和u是否在插值区间内的标志 for(i=0; i<6; i++) { if((u>0.4*i-0.4/2)&&(u<=0.4*i+0.4/2)) for(j=0;j<6;j++) { if((t>0.2*j-0.2/2)&&(t<=0.2*j+0.2/2)) { flag=true; break; } } if(flag) break; } if(!flag) { printf("u=%e,t=%e is not in the expected interval\n",u,t); return 0; } if(i==0) //边界的处理 { i=1; if(j==0) j=1; else if(j==5) j=4; } else if(i==5) { i=4; if(j==0) j=1; else if(j==5) j=4; } pnm=Z[j-1][i-1]*((u-0.4*i)*(u-0.4*(i+1))*(t-0.2*j)*(t-0.2*(j+1)))/((-0.4)*(-0.8)*(-0.2)*(-0.4)) +Z[j][i-1]*((u-0.4*i)*(u-0.4*(i+1))*(t-0.2*(j-1))*(t-0.2*(j+1)))/((-0.4)*(-0.8)*(0.2)*(-0.2)) +Z[j+1][i-1]*((u-0.4*i)*(u-0.4*(i+1))*(t-0.2*(j-1))*(t-0.2*j))/((-0.4)*(-0.8)*(0.2)*(0.4)) +Z[j-1][i]*((u-0.4*(i-1))*(u-0.4*(i+1))*(t-0.2*j)*(t-0.2*(j+1)))/((-0.4)*(0.4)*(-0.2)*(-0.4)) +Z[j][i]*((u-0.4*(i-1))*(u-0.4*(i+1))*(t-0.2*(j-1))*(t-0.2*(j+1)))/((-0.4)*(0.4)*(0.2)*(-0.2)) +Z[j+1][i]*((u-0.4*(i-1))*(u-0.4*(i+1))*(t-0.2*(j-1))*(t-0.2*j))/((-0.4)*(0.4)*(0.2)*(0.4)) +Z[j-1][i+1]*((u-0.4*(i-1))*(u-0.4*i)*(t-0.2*j)*(t-0.2*(j+1)))/((0.8)*(0.4)*(-0.2)*(-0.4)) +Z[j][i+1]*((u-0.4*(i-1))*(u-0.4*i)*(t-0.2*(j-1))*(t-0.2*(j+1)))/((0.8)*(0.4)*(0.2)*(-0.2)) +Z[j+1][i+1]*((u-0.4*(i-1))*(u-0.4*i)*(t-0.2*(j-1))*(t-0.2*j))/((0.8)*(0.4)*(0.2)*(0.4)); return pnm; } //----------------------------------------------- //求解非线性方程组,给定x和y,求解出t,u,v,w void NonlinearEquationSolver(double x,double y,double* X) { double x2[4]; //x2=[t u v w]' double del_x2[4]; double** G=CreateMatrix(4,4); //调用CreateMatrix函数,构建矩阵 int i,j,k; for(i=0; i<4; i++) { del_x2[i]=0; x2[i]=1.0; //给定初值 } k=0; //解非线性方程组的迭代次数 do { k++; for(i=0; i<4; i++) x2[i] = x2[i]+del_x2[i]; //计算Jacobi矩阵F',即G for(i=0; i<4; i++) for(j=0; j<4; j++) G[i][j]=1.0; G[0][0]=-0.5*sin(x2[0]); G[1][1]=0.5*cos(x2[1]); G[2][0]=0.5; G[2][2]=-sin(x2[2]); G[3][1]=0.5; G[3][3]=cos(x2[3]); //计算F,即-del_x2 del_x2[0]=-(0.5*cos(x2[0])+x2[1]+x2[2]+x2[3]-x-2.67); del_x2[1]=-(x2[0]+0.5*sin(x2[1])+x2[2]+x2[3]-y-1.07); del_x2[2]=-(0.5*x2[0]+x2[1]+cos(x2[2])+x2[3]-x-3.74); del_x2[3]=-(x2[0]+0.5*x2[1]+x2[2]+sin(x2[3])-y-0.79); GaussElimination(G,4,del_x2); //调用GaussElimination函数计算线性方程组F'*del_x=-F,解del_x即del_x2 }while(fabs(InfiniteNorm(del_x2,4)/InfiniteNorm(x2,4))>PrecisionLevel); //调用InfiniteNorm函数计算向量的无穷范数 for(i=0;i<4;i++) X[i]=x2[i]; DestroyMatrix(G,4,4); } //----------------------------------------------- //求方阵的逆矩阵 bool InverseMatrix(double** A,int n) { double* b; double** A1=CreateMatrix(n,n); double** A2=CreateMatrix(n,n); b=new double[n]; int i,j,k; for(k=0; k<n; k++) { for(i=0; i<n; i++) for(j=0; j<n; j++) A1[i][j]=A[i][j]; for(i=0; i<n; i++) if(i==k) b[i]=1; else b[i]=0; if(!GaussElimination(A1,n,b)) return false; for(i=0; i<n; i++) A2[i][k]=b[i]; } for(i=0; i<n; i++) for(j=0; j<n; j++) A[i][j]=A2[i][j]; DestroyMatrix(A1,n,n); DestroyMatrix(A2,n,n); delete[]b; return true; } //----------------------------------------------- //计算拟合曲面系数矩阵c_rs void CoefficientMatrix(double* x,int m,double* y,int n,double** z,int k1,int k2,double** C) { double** G=CreateMatrix(n,k2+1); double** B=CreateMatrix(m,k1+1); double** A1=CreateMatrix(k1+1,k1+1); double** A2=CreateMatrix(k2+1,k2+1); double** A3=CreateMatrix(k1+1,m); double** A4=CreateMatrix(n,k2+1); double* temp=new double[n]; int i,j,r,s; for(i=0; i<n; i++) for(j=0; j<k2+1; j++) G[i][j]=pow(y[i],j); //调用math库函数pow计算y[i]的j次方,构建基函数组 for(i=0; i<m; i++) for(j=0; j<k1+1; j++) B[i][j]=pow(x[i],j); //A1=B'*B for(i=0; i<k1+1; i++) for(j=0; j<k1+1; j++) { A1[i][j]=0; for(r=0; r<m; r++) A1[i][j]+=B[r][i]*B[r][j]; } InverseMatrix(A1,k1+1); //调用InverseMatrix函数,求矩阵的逆 //A2=G'*G for(i=0; i<k2+1; i++) for(j=0; j<k2+1; j++) { A2[i][j]=0; for(r=0; r<n; r++) A2[i][j]+=G[r][i]*G[r][j]; } InverseMatrix(A2,k2+1); //A3=A1*B'=(B'B)*B' for(i=0; i<k1+1; i++) for(j=0; j<m; j++) { A3[i][j]=0; for(r=0; r<k1+1; r++) A3[i][j]+=A1[i][r]*B[j][r]; } //A4=G*A2=G*(G'*G) for(i=0; i<n; i++) for(j=0; j<k2+1; j++) { A4[i][j]=0; for(r=0; r<k2+1; r++) A4[i][j]+=G[i][r]*A2[r][j]; } //C=A3*U*A4 for(i=0; i<k1+1; i++) for(j=0; j<k2+1; j++) { C[i][j]=0; for(r=0; r<n; r++) { temp[r]=0; for(s=0; s<m; s++) temp[r]+=A3[i][s]*z[s][r]; C[i][j]+=temp[r]*A4[r][j]; } } delete[]temp; DestroyMatrix(G,n,k2+1); G=NULL; DestroyMatrix(B,m,k1+1); B=NULL; DestroyMatrix(A1,k1+1,k1+1); A1=NULL; DestroyMatrix(A2,k2+1,k2+1); A2=NULL; DestroyMatrix(A3,k1+1,m); A3=NULL; DestroyMatrix(A4,n,k2+1); A4=NULL; } //----------------------------------------------- //计算p(x,y)值 double P_Value(double **C,int k,double x,double y) { double sum=0.0; int r,s; for(r=0; r<=k; r++) for(s=0; s<=k; s++) sum+=C[r][s]*pow(x,r)*pow(y,s); return sum; } //----------------------------------------------- //曲面拟合 double** SurfaceFitting(int& k) { int i,j; double x1[11]; double y1[21]; double y[4]; //用于存储非线性方程组的解y=[t u v w]' double** F=CreateMatrix(11,21); //调用CreateMatrix函数创建矩阵 //--------以下求解问题的第(1)问-------- for(i=0; i<11; i++) //计算xi,yj x1[i]=0.08*i; for(j=0; j<21; j++) y1[j]=0.5+0.05*j; printf("数表xi,yj,f(xi,yj)\n"); for(i=0;i<11;i++) { for(j=0;j<21;j++) { NonlinearEquationSolver(x1[i],y1[j],y); //调用NonlinearEquationSolver函数,求解非线性方程,返回解y,即求用于插值t和u F[i][j]=PiecewiseInterpolation(y[0],y[1]); //调用PiecewiseInterpolation函数,进行分片二次插值求f(xi,yj) printf("%f %f %20.12e\n",x1[i],y1[j],F[i][j]); } } //--------以上求解问题的第(1)问-------- printf("\n"); //--------以下求解问题的第(2)问和第(3)问-------- double sum; double** C; for(k=1; ;k++) { C=CreateMatrix(k+1,k+1); CoefficientMatrix(x1,11,y1,21,F,k,k,C); //调用CoefficientMatrix函数,计算曲面拟合系数C_rs sum=0; //对结果进行验证 for(i=0; i<11; i++) for(j=0; j<21; j++) //调用P_Value函数,计算p(x,y),然后计算误差平方和sigma sum+=(F[i][j]-P_Value(C,k,x1[i],y1[j]))*(F[i][j]-P_Value(C,k,x1[i],y1[j])); printf("k=%d sigma=%.12e\n",k,sum); //显示选择过程中和达到精度要求时的k和sigma if(sum<=1.0e-7) break; if(k>7) break; DestroyMatrix(C,k+1,k+1); C=NULL; } //--------以上求解问题的第(2)问和第(3)问-------- DestroyMatrix(F,11,21); return C; } //----------------------------------------------- //主函数 void main() { double **C; int i,j,k; double X[4]; //初始化Z矩阵(二维数表) Z[0][0]=-0.5; Z[0][1]=-0.34; Z[0][2]=0.14; Z[0][3]=0.94; Z[0][4]=2.06; Z[0][5]=3.5; Z[1][0]=-0.42; Z[1][1]=-0.5; Z[1][2]=-0.26; Z[1][3]=0.3; Z[1][4]=1.18; Z[1][5]=2.38; Z[2][0]=-0.18; Z[2][1]=-0.5; Z[2][2]=-0.5; Z[2][3]=-0.18; Z[2][4]=0.46; Z[2][5]=1.42; Z[3][0]=0.22; Z[3][1]=-0.34; Z[3][2]=-0.58; Z[3][3]=-0.5; Z[3][4]=-0.1; Z[3][5]=0.62; Z[4][0]=0.78; Z[4][1]=-0.02; Z[4][2]=-0.5; Z[4][3]=-0.66; Z[4][4]=-0.5; Z[4][5]=-0.02; Z[5][0]=1.5; Z[5][1]=0.46; Z[5][2]=-0.26; Z[5][3]=-0.66; Z[5][4]=-0.74; Z[5][5]=-0.5; C=SurfaceFitting(k); //调用SurfaceFitting函数求曲面拟合系数C_rs printf("\n系数矩阵C的计算结果:\n"); for(i=0; i<=k; i++) { for(j=0;j<=k;j++) printf("%20.12e ",C[i][j]); printf("\n"); } //--------以下求解问题的第(4)问-------- printf("\n检验p(x,y)逼近f(x,y)的效果:\n"); printf("\n数表xi*,yj*,f(xi*,yj*),p(xi*,yj*):\n"); for(i=1; i<=8; i++) for(j=1; j<=5; j++) { NonlinearEquationSolver(0.1*i,0.5+0.2*j,X); printf("%f %f %20.12e %20.12e\n",0.1*i,0.5+0.2*j,PiecewiseInterpolation(X[0],X[1]),P_Value(C,k,0.1*i,0.5+0.2*j)); } //--------以上求解问题的第(4)问-------- DestroyMatrix(C,k+1,k+1); system("pause"); } //-----------------------------------------------