高斯消元法 (列主元素消元法 LU分解 高斯-赛德尔迭代法)+ 双点割线法 + 最小二乘法 + 拉格朗日插值法

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;
}

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值