数值分析常见算法C++实现
1.1-有效数字丢失现象观察
1 #include<bits./stdc++.h> 2 using namespace std; 3 double f1(double x) 4 { 5 return sqrt(x)*(sqrt(x+1)-sqrt(x)); 6 } 7 double f2(double x) 8 { 9 return sqrt(x)/(sqrt(x+1)+sqrt(x)); 10 } 11 int main() 12 { 13 double t=1.0; 14 while (t<=1e14) 15 { 16 printf("At t=%.lf %.19lf %.19lf\n",t,f1(t),f2(t)); 17 t*=10.0; 18 } 19 printf("sqrt(x+1) = %.19lf sqrt(x) = %.19lf\n",sqrt(t+1),sqrt(t)); 20 printf("diff = %.19lf",sqrt(t+1)-sqrt(t)); 21 printf("sum = %.19lf",sqrt(t+1)+sqrt(t)); 22 }
1.2-n次插值的Lagrange形式
1 #include<bits./stdc++.h> 2 using namespace std; 3 int n; 4 double x[1000],y[1000],xx,yy; 5 int main() 6 { 7 scanf("%d",&n); 8 for (int i=0;i<=n;i++) scanf("%lf %lf",&x[i],&y[i]); 9 scanf("%lf",&xx); 10 for (int i=0;i<=n;i++) 11 { 12 double t=1.0; 13 for (int k=0;k<=n;k++) 14 if (i!=k) t=t*(xx-x[k])/(x[i]-x[k]); 15 yy=yy+t*y[i]; 16 } 17 printf("%.19lf",yy); 18 }
1.3-n次插值Newton形式
1 #include<bits./stdc++.h> 2 using namespace std; 3 int n; 4 double x[1000],y[1000],v[1000],xx,yy,w; 5 int main() 6 { 7 int n; 8 scanf("%d",&n); 9 for (int i=0;i<=n;i++) scanf("%lf%lf",&x[i],&y[i]); 10 scanf("%lf",&xx); 11 w=1.0,v[0]=y[0],yy=y[0]; 12 for (int k=1;k<=n;k++) 13 { 14 v[k]=y[k]; 15 for (int i=0;i<=k-1;i++) 16 v[k]=(v[i]-v[k])/(x[i]-x[k]); 17 w=w*(xx-x[k-1]); 18 yy=yy+w*v[k]; 19 } 20 printf("%.19lf",yy); 21 }
1.4-三次样条插值
1 #include<bits./stdc++.h> 2 using namespace std; 3 int n,type; 4 double x[1000],y[1000],h[1000],xx,yy,w; 5 double sqr(double x) 6 { 7 return x*x; 8 } 9 double m[1000],A[1000],B[1000],a[1000],b[1000]; 10 int main() 11 { 12 int n; 13 scanf("%d",&n); 14 for (int i=0;i<=n;i++) scanf("%lf%lf",&x[i],&y[i]); 15 scanf("%lf",&xx); 16 scanf("%d",&type); 17 for (int i=0;i<=n-1;i++) h[i]=x[i+1]-x[i]; 18 if (type==1) 19 { 20 scanf("%lf%lf",&m[0],&m[n]); 21 a[0]=0.0; b[0]=2.0*m[0]; 22 a[n]=1.0; b[n]=2.0*m[n]; 23 }else if (type==2) 24 { 25 a[0]=1.0;b[0]=3.0/ h[0] *(y[1] - y[0]); 26 a[n]=0.0;b[n]=3.0/(h[n-1])*(y[n] - y[n-1]); 27 } 28 for (int i=1;i<=n-1;i++) 29 { 30 a[i]=h[i-1]/(h[i-1]+h[i]); 31 b[i]=3.0*((1-a[i]) / h[i-1] * (y[i] - y[i-1]) + 32 a[i] / h[i] * (y[i+1] - y[i])); 33 } 34 A[0]=-0.5*a[0]; 35 B[0]=0.5*b[0]; 36 for (int i=1;i<=n;i++) 37 { 38 A[i]=-a[i]/(2 + (1 - a[i]) * A[i-1]); 39 B[i]=(b[i]-(1-a[i])*B[i-1])/(2+(1-a[i])* A[i-1]); 40 } 41 m[n+1]=0; 42 for (int i=n;i>=0;i--) m[i]=A[i]*m[i+1]+B[i]; 43 for (int i=0;i<=n-1;i++) 44 if (xx>=x[i] && xx<=x[i+1]) 45 { 46 yy=( (1 + 2 * (xx-x[i]) / (x[i+1]-x[i])) * sqr((xx-x[i+1]) / (x[i]-x[i+1])) * y[i] )+ 47 ( (1 + 2 * (xx-x[i+1])/ (x[i]-x[i+1])) * sqr((xx-x[i]) / (x[i+1]-x[i])) * y[i+1] )+ 48 ( (xx-x[i] ) * sqr( (xx-x[i+1]) / (x[i]-x[i+1]) ) * m[i] )+ 49 ( (xx-x[i+1]) * sqr( (xx-x[i]) / (x[i+1]-x[i]) ) *m[i+1] ); 50 printf("%.19lf\n",yy); 51 } 52 }
1.5-单变量数据拟合(最小二乘法)
1 #include<bits./stdc++.h> 2 using namespace std; 3 int n,type; 4 double x[1000],y[1000],sx,sy,sxx,sxy,a,b; 5 int main() 6 { 7 scanf("%d",&n); 8 for (int i=1;i<=n;i++) scanf("%lf%lf",&x[i],&y[i]); 9 for (int i=1;i<=n;i++) 10 { 11 sx+=x[i]; 12 sy+=y[i]; 13 sxx+=x[i]*x[i]; 14 sxy+=x[i]*y[i]; 15 } 16 double nn=n; 17 a=(sxx*sy-sx*sxy)/(nn*sxx-sx*sx); 18 b=(nn*sxy-sx*sy)/(nn*sxx-sx*sx); 19 printf("%.19lf %.19lf\n",a,b); 20 }
1.6-自动选取步长梯形法
1 #include<bits./stdc++.h> 2 using namespace std; 3 double a,b,c,h,t1,t0,s,n; 4 double f(double x) 5 { 6 return 2/(1+x*x); 7 } 8 int main() 9 { 10 scanf("%lf%lf%lf",&a,&b,&c); 11 h=(b-a)/2.0; 12 t1=(f(a)+f(b))*h; 13 n=1; 14 while (1) 15 { 16 t0=t1; 17 s=0; 18 for (int k=1;k<=n;k++) s=s+f(a+(2*k-1)*h/n); 19 t1=t0/2.0+s*h/n; 20 if (abs(t1-t0)<3*c) 21 { 22 printf("%.19lf",t1); 23 break; 24 }else n=2.0*n; 25 } 26 }
1.7-Romberg 求积法
1 #include<bits./stdc++.h> 2 using namespace std; 3 double a,b,c; 4 double t[1000][1000]; 5 int k; 6 double f(double x) 7 { 8 return sqrt(x); 9 } 10 double why(double p,double q,int k) 11 { 12 double sum=0; 13 double kk=k; 14 for (double i=p;i<=q;i+=1.0) 15 { 16 sum+=f(a+(2*i-1)*(b-a)/pow(2,kk)); 17 } 18 return sum; 19 } 20 int main() 21 { 22 scanf("%lf%lf%lf",&a,&b,&c); 23 t[0][0]=(b-a)/2.0*(f(a)+f(b)); 24 k=1; 25 while (1) 26 { 27 28 t[0][k]=0.5*(t[0][k-1]+(b-a)/(pow(2,k-1))*why(1,pow(2,k-1),k) ); 29 for (int m=1;m<=k;m++) 30 { 31 t[m][k-m]=(pow(4,m)*t[m-1][k-m+1]-t[m-1][k-m])/(pow(4,m)-1); 32 } 33 if (abs(t[k][0]-t[k-1][0])<c) 34 { 35 printf("%.19lf",t[k][0]); 36 break; 37 }else k+=1.0; 38 } 39 }
2.1-顺序高斯消去法
1 #include<bits./stdc++.h> 2 using namespace std; 3 int n,m; 4 double a[100][100],b[100],c,x[100],t; 5 double sum(int i) 6 { 7 double su=0; 8 for (int j=i+1;j<=n;j++) su+=a[i][j]*x[j]; 9 return su; 10 } 11 int main() 12 { 13 scanf("%d%d",&n,&m); 14 for (int i=1;i<=n;i++) 15 for (int j=1;j<=m;j++) scanf("%lf",&a[i][j]); 16 for (int i=1;i<=n;i++) scanf("%lf",&b[i]); 17 scanf("%lf",&c); 18 for (int k=1;k<=n-1;k++) 19 { 20 if (abs(a[k][k])<=c) 21 { 22 printf("求解失败\n"); 23 return 0; 24 } 25 for (int i=k+1;i<=n;i++) 26 { 27 t=a[i][k]/a[k][k]; 28 b[i]=b[i]-t*b[k]; 29 for (int j=k+1;j<=n;j++) a[i][j]=a[i][j]-t*a[k][j]; 30 } 31 } 32 if (abs(a[n][n])<=c) 33 { 34 printf("求解失败\n"); 35 return 0; 36 }else x[n]=b[n]/a[n][n]; 37 for (int i=n-1;i>=1;i--) x[i]=(b[i]-sum(i))/a[i][i]; 38 for (int i=1;i<=n;i++) printf("%.19lf ",x[i]); 39 cout<<endl; 40 }
2.2-列主元高斯消去法
1 #include<bits./stdc++.h> 2 using namespace std; 3 int n,m,ik; 4 double a[100][100],b[100],c,x[100],t; 5 double sum(int i) 6 { 7 double su=0; 8 for (int j=i+1;j<=n;j++) su+=a[i][j]*x[j]; 9 return su; 10 } 11 int main() 12 { 13 scanf("%d%d",&n,&m); 14 for (int i=1;i<=n;i++) 15 for (int j=1;j<=m;j++) scanf("%lf",&a[i][j]); 16 for (int i=1;i<=n;i++) scanf("%lf",&b[i]); 17 scanf("%lf",&c); 18 for (int k=1;k<=n-1;k++) 19 { 20 t=-1e9; 21 for (int i=k;i<=n;i++) 22 if (abs(a[i][k])>t) 23 { 24 t=abs(a[i][k]); 25 ik=i; 26 } 27 if (t<=c) { 28 printf("求解失败\n"); 29 return 0; 30 } 31 if (ik!=k) 32 { 33 for (int i=1;i<=m;i++) swap(a[ik][i],a[k][i]); 34 swap(b[ik],b[k]); 35 } 36 for (int i=k+1;i<=n;i++) 37 { 38 t=a[i][k]/a[k][k]; 39 b[i]=b[i]-t*b[k]; 40 for (int j=k+1;j<=n;j++) a[i][j]=a[i][j]-t*a[k][j]; 41 } 42 } 43 if (abs(a[n][n])<=c) 44 { 45 printf("求解失败\n"); 46 return 0; 47 }else x[n]=b[n]/a[n][n]; 48 for (int i=n-1;i>=1;i--) x[i]=(b[i]-sum(i))/a[i][i]; 49 for (int i=1;i<=n;i++) printf("%.19lf ",x[i]); 50 cout<<endl; 51 }
2.3-全主元高斯消去法
1 #include<bits./stdc++.h> 2 using namespace std; 3 int n,m,ik,jk,d[100]; 4 double a[100][100],b[100],c,x[100],t,z[100]; 5 double sum(int i) 6 { 7 double su=0; 8 for (int j=i+1;j<=n;j++) su+=a[i][j]*z[j]; 9 return su; 10 } 11 int main() 12 { 13 scanf("%d%d",&n,&m); 14 for (int i=1;i<=n;i++) 15 for (int j=1;j<=m;j++) scanf("%lf",&a[i][j]); 16 for (int i=1;i<=n;i++) scanf("%lf",&b[i]); 17 scanf("%lf",&c); 18 for (int i=1;i<=n;i++) d[i]=i; 19 for (int k=1;k<=n-1;k++) 20 { 21 t=-1e9; 22 for (int i=k;i<=n;i++) 23 for (int j=k;j<=n;j++) 24 { 25 if (abs(a[i][j])>t) 26 { 27 t=abs(a[i][j]); 28 ik=i; 29 jk=j; 30 } 31 } 32 if (t<=c) 33 { 34 printf("求解失败\n"); 35 return 0; 36 } 37 if (ik!=k) 38 { 39 for (int i=1;i<=m;i++) swap(a[ik][i],a[k][i]); 40 swap(b[ik],b[k]); 41 } 42 if (jk!=k) 43 { 44 for (int i=1;i<=n;i++) swap(a[i][jk],a[i][k]); 45 swap(d[jk],d[k]); 46 } 47 for (int i=k+1;i<=n;i++) 48 { 49 t=a[i][k]/a[k][k]; 50 b[i]=b[i]-t*b[k]; 51 for (int j=k+1;j<=n;j++) a[i][j]=a[i][j]-t*a[k][j]; 52 } 53 } 54 z[n]=b[n]/a[n][n]; 55 for (int i=n-1;i>=1;i--) z[i]=(b[i]-sum(i))/a[i][i]; 56 for (int j=1;j<=n;j++) x[d[j]]=z[j]; 57 for (int i=1;i<=n;i++) printf("%.19lf ",x[i]); 58 cout<<endl; 59 }
2.4-LU 直接分解法
1 #include<bits./stdc++.h> 2 using namespace std; 3 int n,m,ik,jk,d[100]; 4 double a[100][100],b[100],c,x[100],y[100]; 5 double l[100][100],u[100][100]; 6 double sum2(int p,int i) 7 { 8 double su=0; 9 for (int j=1;j<=p;j++) su+=l[i][j]*y[j]; 10 return su; 11 } 12 double sum3(int p,int i) 13 { 14 double su=0; 15 for (int j=p;j<=n;j++) su+=u[i][j]*x[j]; 16 return su; 17 } 18 int main() 19 { 20 scanf("%d%d",&n,&m); 21 for (int i=1;i<=n;i++) 22 for (int j=1;j<=m;j++) scanf("%lf",&a[i][j]); 23 for (int i=1;i<=n;i++) scanf("%lf",&b[i]); 24 scanf("%lf",&c); 25 for(int k=1;k<=n;k++) 26 { 27 for(int j=k;j<=n;j++) 28 { 29 double su=0; 30 for(int r=1;r<=k-1;r++) su+=(l[k][r]*u[r][j]); 31 u[k][j]=a[k][j]-su; 32 } 33 for(int i=k;i<= n;i++) 34 { double su=0; 35 for(int r=1;r<=k-1;r++) su+=(l[i][r]*u[r][k]); 36 l[i][k]=(a[i][k]-su)/u[k][k]; 37 } 38 } 39 y[1]=b[1]; 40 for (int i=2;i<=n;i++) y[i]=b[i]-sum2(i-1,i); 41 x[n]=y[n]/u[n][n]; 42 for (int i=n-1;i>=1;i--) x[i]=(y[i]-sum3(i+1,i))/u[i][i]; 43 for (int i=1;i<=n;i++) printf("%.19lf\n",x[i]); 44 cout<<endl; 45 }
2.5-Jacobi 迭代算法
1 #include<bits./stdc++.h> 2 using namespace std; 3 int n,k,M; 4 double a[100][100],b[100],c,x[100],y[100],g[100]; 5 int main() 6 { 7 scanf("%d",&n); 8 for (int i=1;i<=n;i++) 9 { 10 for (int j=1;j<=n;j++) scanf("%lf",&a[i][j]); 11 scanf("%lf",&b[i]); 12 } 13 for (int i=1;i<=n;i++) scanf("%lf",&y[i]); 14 scanf("%lf%d",&c,&M); 15 k=1; 16 for (int i=1;i<=n;i++) 17 { 18 if (abs(a[i][i])<c) 19 { 20 printf("求解失败2\n"); 21 return 0; 22 } 23 double t=a[i][i]; 24 for (int j=1;j<=n;j++) 25 { 26 a[i][j]=-a[i][j]/t; 27 } 28 a[i][i]=0; 29 g[i]=b[i]/t; 30 } 31 while (1) 32 { 33 for (int i=1;i<=n;i++) 34 { 35 double sum=0; 36 for (int j=1;j<=n;j++) if (i!=j) sum+=a[i][j]*y[j]; 37 x[i]=g[i]+sum; 38 } 39 double sum=0; 40 for (int i=1;i<=n;i++) 41 { 42 sum+=abs(x[i]-y[i]); 43 } 44 if (sum<c) 45 { 46 for (int i=1;i<=n;i++) printf("%.19lf\n",x[i]); 47 printf("%d\n",k); 48 return 0; 49 }else 50 if (k<M) 51 { 52 k=k+1; 53 for (int i=1;i<=n;i++) y[i]=x[i]; 54 for (int i=1;i<=n;i++) printf("%.15lf ",y[i]); 55 printf("\n"); 56 }else 57 { 58 printf("求解失败1\n"); 59 return 0; 60 } 61 } 62 }
2.6-Seidel 迭代算法
1 #include<bits./stdc++.h> 2 using namespace std; 3 int n,k,M; 4 double a[100][100],b[100],c,x[100],y[100],g[100]; 5 int main() 6 { 7 scanf("%d",&n); 8 for (int i=1;i<=n;i++) 9 { 10 for (int j=1;j<=n;j++) scanf("%lf",&a[i][j]); 11 scanf("%lf",&b[i]); 12 } 13 for (int i=1;i<=n;i++) scanf("%lf",&y[i]); 14 scanf("%lf%d",&c,&M); 15 k=1; 16 for (int i=1;i<=n;i++) x[i]=y[i]; 17 18 for (int i=1;i<=n;i++) 19 { 20 if (abs(a[i][i])<c) 21 { 22 printf("求解失败2\n"); 23 return 0; 24 } 25 double t=a[i][i]; 26 for (int j=1;j<=n;j++) 27 { 28 a[i][j]=-a[i][j]/t; 29 } 30 a[i][i]=0; 31 g[i]=b[i]/t; 32 } 33 while (1) 34 { 35 for (int i=1;i<=n;i++) 36 { 37 double sum=0; 38 for (int j=1;j<=n;j++) if (i!=j) sum+=a[i][j]*x[j]; 39 x[i]=g[i]+sum; 40 } 41 double sum=0; 42 for (int i=1;i<=n;i++) 43 { 44 sum+=abs(x[i]-y[i]); 45 } 46 if (sum<c) 47 { 48 for (int i=1;i<=n;i++) printf("%.19lf\n",x[i]); 49 printf("%d\n",k); 50 return 0; 51 }else 52 if (k<M) 53 { 54 k=k+1; 55 for (int i=1;i<=n;i++) y[i]=x[i]; 56 for (int i=1;i<=n;i++) printf("%.15lf ",y[i]); 57 printf("\n"); 58 }else 59 { 60 printf("求解失败1\n"); 61 return 0; 62 } 63 } 64 }
2.7-松弛迭代算法
1 #include<bits./stdc++.h> 2 using namespace std; 3 int n,k,M; 4 double a[100][100],b[100],c,x[100],y[100],g[100],w; 5 int main() 6 { 7 scanf("%d",&n); 8 for (int i=1;i<=n;i++) 9 { 10 for (int j=1;j<=n;j++) scanf("%lf",&a[i][j]); 11 scanf("%lf",&b[i]); 12 } 13 for (int i=1;i<=n;i++) scanf("%lf",&y[i]); 14 scanf("%lf",&w); 15 scanf("%lf%d",&c,&M); 16 k=1; 17 for (int i=1;i<=n;i++) x[i]=y[i]; 18 19 for (int i=1;i<=n;i++) 20 { 21 if (abs(a[i][i])<c) 22 { 23 printf("求解失败2\n"); 24 return 0; 25 } 26 double t=a[i][i]; 27 for (int j=1;j<=n;j++) 28 { 29 a[i][j]=-w*a[i][j]/t; 30 } 31 a[i][i]=1-w; 32 g[i]=w*b[i]/t; 33 } 34 while (1) 35 { 36 for (int i=1;i<=n;i++) 37 { 38 double sum=0; 39 for (int j=1;j<=n;j++) if (i!=j) sum+=a[i][j]*x[j]; 40 x[i]=g[i]+sum; 41 } 42 double sum=0; 43 for (int i=1;i<=n;i++) 44 { 45 sum+=abs(x[i]-y[i]); 46 } 47 if (sum<c) 48 { 49 for (int i=1;i<=n;i++) printf("%.19lf\n",x[i]); 50 printf("%d\n",k); 51 return 0; 52 }else 53 if (k<M) 54 { 55 k=k+1; 56 for (int i=1;i<=n;i++) y[i]=x[i]; 57 for (int i=1;i<=n;i++) printf("%.15lf ",y[i]); 58 printf("\n"); 59 }else 60 { 61 printf("求解失败1\n"); 62 return 0; 63 } 64 } 65 }
2.8-对分法求根
1 #include<bits./stdc++.h> 2 using namespace std; 3 double d,c,a[1000],b[1000],A,B,x[1000]; 4 double f(double x) 5 { 6 return x*x*x-3*x+1.0; 7 } 8 int k; 9 double ff; 10 int main() 11 { 12 scanf("%lf%lf",&d,&c); 13 scanf("%lf%lf",&A,&B); 14 a[0]=A;b[0]=B;k=0; 15 while (1) 16 { 17 x[k]=(a[k]+b[k])/2; 18 ff=f(x[k]); 19 if (abs(ff)<d) 20 { 21 printf("%.19lf\n",x[k]); 22 break; 23 } 24 if (f(a[k])*f(x[k]) < 0) 25 { 26 a[k+1]=a[k]; 27 b[k+1]=x[k]; 28 }else 29 { 30 a[k+1]=x[k]; 31 b[k+1]=b[k]; 32 } 33 if (b[k+1]-a[k+1]<=c) 34 { 35 printf("%.19lf\n",(a[k+1]+b[k+1])/2); 36 }else k=k+1; 37 } 38 }
2.9-松弛法迭代求根
#include<bits./stdc++.h> using namespace std; double d,c,A,B,x[1000],w[1000]; double f(double x) { return (x*x*x+1.0)/3.0; } double ff(double x) { return x*x; } int k; int main() { scanf("%lf%lf",&x[0],&c); while (1) { w[k]=1/(1-ff(x[k])); x[k+1]=(1-w[k])*x[k]+w[k]*f(x[k]); if (abs(x[k+1]-x[k])<c ) { printf("%.19lf\n",x[k+1]); break; }else k=k+1; } }
2.10-牛顿法求根
1 #include<bits./stdc++.h> 2 using namespace std; 3 double d,c,A,B,x[1000],w[1000]; 4 double f(double x) 5 { 6 return x*x*x-3.0*x+1; 7 } 8 double ff(double x) 9 { 10 return 3*x*x-3; 11 } 12 int k; 13 int main() 14 { 15 scanf("%lf%lf",&x[0],&c); 16 k=0; 17 while(1) 18 { 19 x[k+1]=x[k]-f(x[k])/ff(x[k]); 20 if (abs(x[k+1] -x[k]) < c) 21 { 22 printf("%.19lf\n",x[k+1]); 23 break; 24 }else k=k+1; 25 } 26 }
Anderyi!