数值分析线性方程组迭代法之SOR迭代法详解及其C语言算法实现

SOR迭代法,又名逐次超松弛迭代法,与Jacobi迭代法和Guass-Seidel迭代法相比,收敛速度更快其原理如下(想详细了解,可以点击这里数值分析(东北大学)):
1.构造迭代式时,要加上一个大于0的松弛因子w,这样可以加快其收敛速度
在这里插入图片描述
2.根据上式进行分析:
在这里插入图片描述
3.得到迭代式:
在这里插入图片描述
得到迭代式以后,就可以选择合适的初始解进行计算了,由于迭代法的收敛性与初始向量无关,与系数矩阵的谱半径有关,所以在计算时的初始解向量不妨设为0向量即可

代码实现

1.初始化:

double** init_Matrix(int r, int c)
{
	double** p = new double* [r];
	int d = c + 1;
	for (int i = 0; i < r; i++)
	{
		p[i] = new double[d];
		memset(p[i], 0, sizeof(double) * d);
	}
	cout << "请输入线性方程组对应的增广矩阵:" << endl;
	for (int i = 0; i < r; i++)
	{
		for (int j = 0; j < d; j++)
		{
			cin >> p[i][j];
		}
	}

	cout << "请输入SOR的松弛因子w(0<w):" << endl;
	while (!(cin >> w)||(cin.fail()))
	{
		if (w>0)
		{
			break;
		}
		else
		{
			cin.clear();
			cin.sync();
			cout << "输入不规范的w,请重新输入!" << endl;
		}
	}
	return p;
}

2.判断是否达到精度要求:

bool isRight(double** p, int r, double* x)
{
	double sum1 = 0, flag = 0, sum2 = 0;
	for (int i = 0; i < r; i++)
	{
		sum1 = 0, flag = 0;
		for (int j = 0; j < r; j++)
		{
			sum1 += x[j] * p[i][j];
		}
		flag = fabs(p[i][r] - sum1);
		if (flag > one_Precision)//解代入单个方程式的误差过大
		{
			return false;
		}
		else
		{
			sum2 += flag;
		}
	}
	if (sum2 > total_Precision)//整体误差过大
	{
		return false;
	}
	return true;
}

3.迭代计算:

void Iteration(double** p, int r, double* x)
{
	int k = 0;//迭代次数
	double sum = 0,tmp=0;
	while (true)
	{
		for (int i = 0; i < r; i++)
		{
			sum = 0,tmp=0;
			for (int j = 0; j < r; j++)
			{
				if (j == i)
				{
					tmp -= x[j];
				}
				else
				{
					sum -= p[i][j] * x[j];
				}
			}
			x[i] = x[i]+w*((p[i][r] + sum) / p[i][i])+w*tmp;
		}
		printf("第%d次迭代结果为:", ++k);
		for (int i = 0; i < r; i++)
		{
			printf("%f\t", x[i]);
		}
		cout << endl;
		if (k >= MAX_time)
		{
			cout << "超出迭代次数上限!停止迭代" << endl;
			return;
		}
		if (isRight(p, r, x))//精度符合要求
		{
			cout << "精度符合要求,停止迭代,共迭代:" << k << "次" << endl;
			return;
		}
	}
}

完整代码:

#include<iostream>
#include<Windows.h>
#include<math.h>
#define one_Precision   1e-5//单个方程误差
#define total_Precision 3e-5//整体方程误差
#define MAX_time  1000//最大迭代次数
using namespace std;
/*
3 3
10 -1  0 9
-1 10 -2 7
0  -2 10 6

3 3
3 2 -3 -2
1 1  1  6
1 2 -1  2

3 3
1  2 -3 1
2 -1  3 5
3 -2  2 1



4 4
4 -3  6  7 11
1  1  3  4 10
-2 9 -7  1 10
3  3 -4 20 25
*/
double w =0;//先赋初始值为0 避免访问到未处理的内存 计算时要求进行输入
double** init_Matrix(int r, int c)
{
	double** p = new double* [r];
	int d = c + 1;
	for (int i = 0; i < r; i++)
	{
		p[i] = new double[d];
		memset(p[i], 0, sizeof(double) * d);
	}
	cout << "请输入线性方程组对应的增广矩阵:" << endl;
	for (int i = 0; i < r; i++)
	{
		for (int j = 0; j < d; j++)
		{
			cin >> p[i][j];
		}
	}

	cout << "请输入SOR的松弛因子w(0<w):" << endl;
	while (!(cin >> w)||(cin.fail()))
	{
		if (w>0)
		{
			break;
		}
		else
		{
			cin.clear();
			cin.sync();
			cout << "输入不规范的w,请重新输入!" << endl;
		}
	}
	return p;
}
bool isRight(double** p, int r, double* x)
{
	double sum1 = 0, flag = 0, sum2 = 0;
	for (int i = 0; i < r; i++)
	{
		sum1 = 0, flag = 0;
		for (int j = 0; j < r; j++)
		{
			sum1 += x[j] * p[i][j];
		}
		flag = fabs(p[i][r] - sum1);
		if (flag > one_Precision)//解代入单个方程式的误差过大
		{
			return false;
		}
		else
		{
			sum2 += flag;
		}
	}
	if (sum2 > total_Precision)//整体误差过大
	{
		return false;
	}
	return true;
}
void Iteration(double** p, int r, double* x)
{
	int k = 0;//迭代次数
	double sum = 0,tmp=0;
	while (true)
	{
		for (int i = 0; i < r; i++)
		{
			sum = 0,tmp=0;
			for (int j = 0; j < r; j++)
			{
				if (j == i)
				{
					tmp -= x[j];
				}
				else
				{
					sum -= p[i][j] * x[j];
				}
			}
			x[i] = x[i]+w*((p[i][r] + sum) / p[i][i])+w*tmp;
		}
		printf("第%d次迭代结果为:", ++k);
		for (int i = 0; i < r; i++)
		{
			printf("%f\t", x[i]);
		}
		cout << endl;
		if (k >= MAX_time)
		{
			cout << "超出迭代次数上限!停止迭代" << endl;
			return;
		}
		if (isRight(p, r, x))//精度符合要求
		{
			cout << "精度符合要求,停止迭代,共迭代:" << k << "次" << endl;
			return;
		}
	}
}
void SOR_main()
{
	int i = 0, j = 0;
	cout << "请输入线性方程组对应系数矩阵的行和列:" << endl;
	cin >> i >> j;
	double** p = init_Matrix(i, j);
	double* X = new double[i];//第n+1次跌代
	memset(X, 0, sizeof(double) * i);
	Iteration(p, i, X);
	for (int i = 0; i < j; i++)
	{
		delete[]p[i];
	}
	delete[]p;
	delete[]X;
}
int main(void)
{
	SOR_main();
	system("pause");
	return 0;
}
  • 11
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SOR迭代法是一种常用的求解线性方程组迭代法,它可以有效地加速收敛速度,特别适用于大型稀疏线性方程组的求解。下面是SOR迭代法的Matlab实现程序: ```matlab function [x, iter] = sor(A, b, omega, tol, maxiter) % SOR迭代法求解线性方程组Ax=b % A: 系数矩阵 % b: 右侧向量 % omega: 松弛因子 % tol: 精度要求 % maxiter: 最大迭代次数 % x: 方程组的解 % iter: 实际迭代次数 n = length(b); % 系数矩阵的阶数 x = zeros(n, 1); % 初始化解向量 iter = 0; % 初始化迭代次数 while iter < maxiter xold = x; for i = 1:n sigma = 0; for j = 1:n if j ~= i sigma = sigma + A(i, j) * x(j); end end x(i) = (1 - omega) * x(i) + omega * (b(i) - sigma) / A(i, i); end if norm(x - xold) < tol % 判断精度是否达到要求 return; end iter = iter + 1; end ``` 其中,A是系数矩阵,b是右侧向量,omega是松弛因子,tol是精度要求,maxiter是最大迭代次数。程序中使用了一个while循环来进行迭代,直到达到精度要求或最大迭代次数时停止。在每次迭代中,根据SOR迭代公式更新解向量x,并判断是否达到精度要求。最后,返回解向量x和实际迭代次数iter。 如果需要求解一个线性方程组Ax=b,可以调用该函数进行求解,例如: ```matlab A = [4 -1 0 0; -1 4 -1 0; 0 -1 4 -1; 0 0 -1 3]; b = [15; 10; 10; 10]; omega = 1.25; tol = 1e-6; maxiter = 1000; [x, iter] = sor(A, b, omega, tol, maxiter); disp(['解向量x = ' num2str(x')]); disp(['迭代次数iter = ' num2str(iter)]); ``` 该程序将求解系数矩阵A和右侧向量b所表示的线性方程组松弛因子为1.25,精度要求为1e-6,最大迭代次数为1000。程序输出解向量x和实际迭代次数iter。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱你是长久之计~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值