1.列主元素消元法
//列主元素消元法
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef pair<double,int>PII;
const int maxn=100+5;
double maze[maxn][maxn];
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
int n,kase=0;
while(scanf("%d",&n)==1&&n) //未知数的个数
{
for(int i=0;i<n;i++)
for(int j=0;j<n+1;j++)
cin>>maze[i][j];
for(int i=0;i<n-1;i++)
{
PII field[maxn];
int k=0;
for(int j=i;j<n;j++)
field[k++]=PII(fabs(maze[j][i]),j);
sort(field,field+k);
int z=field[k-1].second;
for(int k=i;k<n+1;k++)
swap(maze[i][k],maze[z][k]);
for(int k=i+1;k<n;k++)
{
double rat=maze[k][i]/maze[i][i];
for(int j=i;j<n+1;j++)
maze[k][j]-=rat*maze[i][j];
}
}
//从矩阵最后一行开始求解
printf("Case %d:\n",++kase);
double solve[maxn];
for(int i=n-1;i>=0;i--)
{
for(int j=n-1;j>i;j--)
{
double k=solve[j];
maze[i][n]-=k*maze[i][j];
}
double k=maze[i][n]/maze[i][i];
solve[i]=k;
}
for(int i=0;i<n;i++)
printf("%.5f%c",solve[i],i+1==n?'\n':' ');
}
return 0;
}
2.LU矩阵分解
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100+5;
double maze[maxn][maxn];
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
int n,kase=0;
while(scanf("%d",&n)==1&&n)
{
for(int i=0;i<n;i++)
for(int j=0;j<n+1;j++)
cin>>maze[i][j];
double A[maxn][maxn],L[maxn][maxn],U[maxn][maxn],b[maxn];
for(int i=0;i<n;i++)
for(int j=0;j<n+1;j++)
if(j<n) {
A[i][j]=maze[i][j];
}
else {
b[i]=maze[i][j];
}
//根据A矩阵求解L及U矩阵
memset(L,0,sizeof(L));
for(int i=0;i<n;i++)
L[i][i]=1;
for(int i=0;i<n-1;i++) //指向标准行列
{
for(int k=i+1;k<n;k++)
{
double rat=A[k][i]/A[i][i];
L[k][i]=rat;
for(int j=i;j<n;j++)
A[k][j]-=rat*A[i][j];
}
}
memcpy(U,A,sizeof(A));
//Ly=b Ux=y
printf("Case %d:\n",++kase);
double Y[maxn],X[maxn];
Y[0]=b[0];
for(int i=1;i<n;i++)
{
for(int j=0;j<i;j++)
b[i]-=Y[j]*L[i][j];
Y[i]=b[i];
}
for(int i=n-1;i>=0;i--)
{
for(int j=n-1;j>i;j--)
{
double k=X[j];
Y[i]-=k*U[i][j];
}
double k=Y[i]/U[i][i];
X[i]=k;
}
for(int i=0;i<n;i++)
printf("%.5f%c",X[i],i+1==n?'\n':' ');
}
return 0;
}
3.高斯-赛德尔迭代法
//高斯-赛德尔迭代法
//注意要达到严格对角优势
/*the test case
the input:
3
10 -1 -2 7.2
-1 10 -2 8.3
-1 -1 5 4.2
the output:
X1:1.10000
X2:1.20000
X3:1.30000
*/
#include <bits/stdc++.h>
using namespace std;
typedef pair<double,int>PII;
const int maxn=100+5;
double maze[maxn][maxn];
double str[maxn][maxn];
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n+1;j++)
cin>>maze[i][j];
//进行换行 确定方程
for(int i=0;i<n;i++)
{
vector<PII>field;
field.clear();
for(int j=i;j<n;j++)
{
field.push_back(PII(fabs(maze[j][i]),j));
}
sort(field.begin(),field.end());
int pos=field.size()-1;
for(int j=0;j<n+1;j++)
swap(maze[field[pos].second][j],maze[i][j]);
for(int j=0;j<n;j++)
{
str[i][j]=(j==i?0:(-maze[i][j])/maze[i][i]);
}
}
//设定初始值 进行迭代
double solve[maxn];
int cnt=0;
memset(solve,0,sizeof(solve));
while(true)
{
for(int i=0;i<n;i++)
{
solve[i]=0;
for(int j=0;j<n;j++)
{
solve[i]+=solve[j]*str[i][j];
}
solve[i]+=maze[i][n]/maze[i][i];
}
cnt++;
if(cnt==20) break;
}
for(int i=0;i<n;i++)
printf("X%d:%.5f\n",i+1,solve[i]);
return 0;
}
4.二分查找根
#include<bits/stdc++.h>
using namespace std;
double C(double k)
{
return 1.0-k-sin(k);
}
int main()
{
double lb=0,rb=1.0,mid;
int cnt=0;
while(rb-lb>0.0001)
{
mid=(lb+rb)/2.0;
if(C(lb)*C(mid)<0) rb=mid;
else lb=mid;
cnt++;
}
printf("%.5f\n迭代次数为:%d\n",(rb+lb)/2.0,cnt+1);
return 0;
}
5.双点割线法
//双点割线法
//f(x)=x*x*x-3*x+1 令x0=0.2 x1=0.5
#include<bits/stdc++.h>
using namespace std;
double solve(double x)
{
return x*x*x-3*x+1.0;
}
int main()
{
double x0=0.2,x1=0.5,x2;
int t=8;
while(t--)
{
x2=x1-(solve(x1)/(solve(x1)-solve(x0)))*(x1-x0);
x0=x1;
x1=x2;
}
printf("%.6f\n",x2);
return 0;
}
6.拉格朗日插值法
//拉格朗日插值法
#include<bits/stdc++.h>
using namespace std;
typedef pair<double,double>PII;
int main()
{
//Ln(x)=y0*lo(x)+y1*l1(x)+.....+yn*ln(x)
PII p[6];
p[0]=PII(0.40,0.41075);
p[1]=PII(0.55,0.57815);
p[2]=PII(0.65,0.69675);
p[3]=PII(0.80,0.88811);
p[4]=PII(0.90,1.02652);
p[5]=PII(1.05,1.25386);
double solve=0.596,sum=0;
for(int i=0;i<6;i++)
{
double k=1.0;
for(int j=0;j<6;j++)
{
if(i!=j) {
k*=(solve-p[j].first)/(p[i].first-p[j].first);
}
}
sum+=p[i].second*k;
}
printf("%.5f\n",sum);
return 0;
}
7.最小二乘法拟合多项式
//最小二乘法求多项式拟合
#include<bits/stdc++.h>
using namespace std;
typedef pair<double,double>PII;
typedef pair<double,int>PII2;
const int maxn=100+5;
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
int n;
scanf("%d",&n);
PII p[maxn];
for(int i=0;i<n;i++)
{
cin>>p[i].first>>p[i].second;
}
int k;
scanf("%d",&k);
//对称矩阵 再利用高斯消元法
double X[maxn][maxn],Y[maxn];
memset(X,0,sizeof(X));
for(int i=0;i<=k;i++)
{
for(int j=0;j<=k;j++)
{
if(i==0&&j==0) {
X[i][j]=n;
continue;
}
//起始次数和行数及列数相关
if(X[i][j]==0) {
int fac=i+j; //次数
double sum=0.0;
for(int m=0;m<n;m++)
{
sum+=pow(p[m].first,fac);
}
X[i][j]=X[j][i]=sum;
}
else continue;
}
}
//求Y矩阵
for(int i=0;i<=k;i++)
{
double sum=0.0;
for(int j=0;j<n;j++)
{
sum+=pow(p[j].first,i)*p[j].second;
}
Y[i]=sum;
}
//将X和Y矩阵合并
double solve[maxn][maxn];
for(int i=0;i<=k;i++)
for(int j=0;j<=k+1;j++)
{
if(j<=k) solve[i][j]=X[i][j];
else if(j==k+1) solve[i][j]=Y[i];
}
//利用高斯消元法
for(int i=0;i<=k-1;i++)
{
PII2 field[maxn];
int cnt=0;
for(int j=i;j<=k;j++)
field[cnt++]=PII2(fabs(solve[j][i]),j);
sort(field,field+cnt);
int z=field[cnt-1].second;
for(int f=i;f<=k+1;f++)
swap(solve[i][f],solve[z][f]);
for(int f=i+1;f<=k;f++)
{
double rat=solve[f][i]/solve[i][i];
for(int j=i;j<=k+1;j++)
solve[f][j]-=rat*solve[i][j];
}
}
//从矩阵最后一行开始求解
double s[maxn];
memset(s,0,sizeof(s));
for(int i=k;i>=0;i--)
{
for(int j=k;j>i;j--)
{
double f=s[j];
solve[i][k+1]-=f*solve[i][j];
}
double f=solve[i][k+1]/solve[i][i];
s[i]=f;
}
printf("多项式拟合结果为:\n");
for(int i=0;i<=k;i++)
printf("X[%d]=%.6f\n",i+1,s[i]);
printf("多项式为:\nY=");
for(int i=0;i<=k;i++)
{
if(i==0) printf("%.6f",s[i]);
else printf("%.6fx^%d",s[i],i);
if(i+1==k+1) printf("\n");
else if(s[i+1]>0) printf("+");
}
return 0;
}