Jacobi迭代法的C++代码实现

Jacobi迭代法,也称为简单迭代法。

假设有方程组


用矩阵表示:


A是系数矩阵,非奇异,b,X为n维向量

假设aii≠0 ,则可以通过移项和简单的乘除法得到如下变换:


其中


构造一个新的矩阵B


则上述经过变换的方程组可以表示为X=BX+g

由此可以构造一个迭代格式(Jacobi迭代)


取定初始向量X(0)之后,便可以由上式产生X(1), X(2), ... X(K), ...

若能够收敛于X(*),则X(*)就是方程的解。

代码实现:

首先定义几个函数用于辅助计算

//矩阵乘法,传入a,b矩阵及其相应的行列数
void mulMatrix(double **&a,int r1,int c1,double **&b,int r2,int c2)
{
	if(c1!=r2) 
		return;
	else { 
		for(int i=0;i<r1;i++)
		{ 
			for(int j=0;j<c1;j++)
			{
				res[i][j]=0; 
				for(int t=0;t<c1;t++)
				res[i][j]=res[i][j]+a[i][t]*b[t][j];}
		}
	}
}


//矩阵加法,传入a,b矩阵及其行列数
void addMatrix(double **&a,double **&b,int r,int c)
{
	for(int i=0;i<r;i++)
		for(int j=0;j<c;j++)
			res[i][j]=a[i][j]+b[i][j];
}


//用于给另外一个矩阵赋值
void moveMatrix(double **&a,double **&b,int r,int c)
{
	for(int i=0;i<r;i++)
		for(int j=0;j<c;j++)
			a[i][j]=b[i][j];
}

//输出矩阵的值
void showMatrix(double **&a,int r,int c)
{
	for(int i=0;i<r;i++)
	{
		for(int j=0;j<c;j++)
			cout<<a[i][j]<<'\t';
		cout<<endl;
	}
}

主函数中并没有去判断结果是否收敛,而是将每一次迭代的结果都打印出来。若要改成判断收敛,只需要判断两次的结果差值是否小于一个可接受的范围。

int main()
{
	int n;
	cout<<"How many rows?"<<endl;
//输入方程变量个数
	cin>>n;
	cout<<"Input matrix:"<<endl;
//输入矩阵A
	double **a=new double*[n];
	for(int i=0;i<n;i++)
		a[i]=new double[n];
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			cin>>a[i][j];
	cout<<"Calculating matrix B ..."<<endl;
//计算矩阵B
	double **B=new double*[n];
	for(int i=0;i<n;i++)
		B[i]=new double[n];
	//Calculating
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			if(i!=j)
				B[i][j]=-a[i][j]/a[i][i];
			else 
				B[i][j]=0;
		}
	}
	showMatrix(B,n,n);
	cout<<"Input list b:"<<endl;
//输入方程组右端的n维向量b
	double **b=new double*[n];
	for(int i=0;i<n;i++)
		b[i]=new double[1];
	for(int i=0;i<n;i++)
		for(int j=0;j<1;j++)
			cin>>b[i][j];
	cout<<"Calculating g ..."<<endl;
//计算g
	double **g=new double*[n];
	for(int i=0;i<n;i++)
		g[i]=new double[1];
	//Calculating
	for(int i=0;i<n;i++)
		for(int j=0;j<1;j++)
			g[i][j]=b[i][j]/a[i][i];
	showMatrix(g,n,1);
	//Initial res
//res为全局变量
	res=new double*[n];
	for(int i=0;i<n;i++)
		res[i]=new double[1];
	cout<<"Input X0:"<<endl;
//输入初始向量X(0)
	double **X=new double*[n];
	for(int i=0;i<n;i++)
		X[i]=new double[1];
	for(int i=0;i<n;i++)
		for(int j=0;j<1;j++)
			cin>>X[i][j];
	int k=0;
	cout<<"The result of X"<<k<<":    >>>"<<endl;
	mulMatrix(B,n,n,X,n,1);
	addMatrix(res,g,n,1);
	showMatrix(X,n,1);
//继续计算则按Y,其他则退出计算
	cout<<"Continue?(Y or other else)"<<endl;
	char F;
	cin>>F;
	while(F=='Y'){
		k++;
		cout<<"The result of X"<<k<<":    >>>"<<endl;
		moveMatrix(X,res,n,1);
		mulMatrix(B,n,n,X,n,1);
		addMatrix(res,g,n,1);
		showMatrix(X,n,1);
		cout<<"Continue?(Y/N)"<<endl;
		cin>>F;
	}
}

运行结果:



当计算到X(20)的时候,可以看到已经和X(19)的结果一样了,说明这个方程组用简单迭代法是可以收敛的。

该方程组的准确解为:x1=55/238, x2=5/34, x3=121/238,换算成小数,可以知道上边的计算结果能够收敛到准确解。

算法参考自《数值分析》(华南理工大学出版社),测试样例来自书中的习题。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值