【C++】超级详细,多元一次方程的求解方法

在这个问题中,假设我们是要解一个N元一次的方程;

解题使用方法:

使用多元一次方程的 消去法
假设我有三个方程
2a-b+c=3 , 3a+b-c=2 , a-3b+2c=1
对第一个式子我让第一个元素为准(我们这里就叫他标准行吧,先记住这个名字!!!!!!),即a,每个方程同时除以a的系数,就变成了
a-(1/2)b+(1/2)c=3/2 , a+(1/3)b-(1/3)c=2/3 , a-3b+2c=1
然后,用第一个式子的a去替换掉其他式子的a(自身不换),也可以理解为其他式子减去用来替换a的式子,方程变为
a+2b+2c=1 , (5/6)b-(5/6)c=-(5/6) , -(5/2)b+(3/2)c=1/3
这里第二个式子和第三个式子都只有bc,按照这种方式,我再以第二个方程为准(第二个方程作为标准行),替换掉第三个方程的b(这里为什么不替换第一个方程后面解释),这样第三个方程只剩下c,最后以第三个方程为标准行,因为它这个方程只有一个元素,可以解出c
然后将c往第二个方程中带入第二个方程(只有b,c两个元素),解出b,再带入第一个,解出a
所以,在第一次替换后,只有第一个式子有a,如果我还去替换它,那肯定算不出a的呀

储存办法:

一个多元一次的方程要用什么来储存呢?我们可以将方程储存在double m[N][N+1]数组(N个需要求解的元素,还有第N+1个位置储存方程结果)中;
【C++】超级详细,多元一次方程的求解方法_第1张图片
计算的数据结果我们可以在double s[N]数组中。

同时,还需要一个用来记录方程中用来替换其他的元素的数组int loc[N],并且初始化它为-1,元素位置不可能为-1(比如说我第二个方程第二个元素,即b元素就是用来替换其他方程的第二个元素的,则loc[1]=1,这里从0开始)

办法:解决这个问题,我们需要一些函数

1,

一个能将第h行的方程同时除以第n个元素的系数的函数

void make1(int h, int n)//使h行同时除以第n个元素
{
     
	double t = m[h][n];//过程中第n个元素的系数会改变,所以先储存其系数
	if (m[h][n] == 0)
		return;
	for (int i = 0; i < N + 1; i++)
		m[h][i] /= t;
}

为了方便记,就记make1,make系数变为1

在轮到第n个元素做消去的时候,对所以能够除去第n个元素的系数的方程进行make1函数

void Allmake1(int n)
{
     
	for (int i = 0; i < N; i++)
	{
     
		if (loc[i] == -1 && m[i][n] != 0)
			make1(i, n);
			//loc[i]==-1,说明这一行没有做过标准行
			//m[i][n] != 0,说明这个方程的第n个元素系数不是0
			//如果是0,除以系数是会出现分母为0的情况,答案可能会得到-inf
	}
}

Allmake1,让所有系数变为一(不是真的所有)

2,在进行了除以系数的函数后,我们就要开始替换啦

min函数的作用是标准行s,对目标行h,进行替换掉第n个元素的操作
因为之前进行过所有方程的第n个元素的系数直接变成一的操作了,所以直接减法就可以让h的第n个元素消去
不应该减去的方程是:作标准行的和这个方程没有第n个元素的(n号元素在方程中系数为0)

void min(int s,int h,int n)
{
     
	if(loc[h]==-1&&m[h][n]!=0)
		for (int i = 0; i < N+1; i++)
			m[h][i] -= m[s][i];
}


void Allmin(int s,int n)//对所有应该替换的程都替换掉第n个元素
{
     
	for (int i = 0; i < N; i++)
		min(s, i, n);
}

记住min消去你的第n个元素
Allmin(消去所有方程第n个元素,不是真的所有哦)

3,标记第h个方程是作为第n个元素标准行的函数

随便找一个第n个元素的系数不为0的方程(在第h行),记录loc并且用这个方程去替换除了自己以外所有这个元素的系数不为0并且没有作为标准行过的方程(这个方程在loc数组中对应值为-1)

void setloc(int h, int n)
{
     
	loc[h] = n;
}

setloc,标记标准行

4,找到第n个元素的标准行,并对其他行进行替换的函数

void Onereplace(int n)
{
     
	int l;
	for (int i = 0; i < N; i++)
	{
     
		if (loc[i] == -1 && m[i][n] != 0)
		{
     
			l = i;
			setloc(i, n);//标记标准行
			make1(i, n);//使自身方程进行除法,都除以第n个元素的系数
			break;
		}	
	}
	Allmake1(n);//对所有方程进行make1
	Allmin(l,n);//消去第n个元素
}
void Allreplace()//从第1个元素到第n个,所有元素能换掉就换掉
{
     
	for (int i = 0; i < N; i++)
		Onereplace(i);
}

One replace,换掉所有的第n个元素
All replace,换到所有元素(不是真的所有)

这就是主要的函数啦,但是你不觉得一个一个函数打出来很麻烦吗? 我干脆把他们都放在一个函数里算啦。

void pc()
{
     
	fill(loc, loc + N, -1);
	Allreplace();
	Allcacular();
}

还要有一个输出元素结果的函数

void Cout()
{
     
	for (int i = 0; i < N; i++)
		cout << s[i] << " ";
	cout << endl;
}

什么!你有强迫症,不想一个一个函数单独看? 行行,整合了发。
唉,随便水水字数了,好累

#include
using namespace std;
#define N 4//我自己假设的例子,这里N等于4,结果a=1,b=2,c=3,d=4
double m[N][N + 1] = {
     
    0,3,2,1, 16,
	1,1,1,1, 10,
	3,2,2,1, 17,
	2,0,1,2, 13
//不放心你就自己整几个例子啊,学生也很忙的啊,现在都1:53了,肝死我了
};
double s[N];
int loc[N];
void Allmin(int s, int n);//声明函数,不然会报错
void make1(int h, int n)
{
     
	double t = m[h][n];
	if (m[h][n] == 0)
		return;
	for (int i = 0; i < N + 1; i++)
		m[h][i] /= t;
}
void setloc(int h, int n)
{
     
	loc[h] = n;
}
void Allmake1(int n)
{
     
	for (int i = 0; i < N; i++)
	{
     
		if (loc[i] == -1 && m[i][n] != 0)
			make1(i, n);
	}
}
void Onereplace(int n)
{
     
	int l;
	for (int i = 0; i < N; i++)
	{
     
		if (loc[i] == -1 && m[i][n] != 0)
		{
     
			l = i;
			setloc(i, n);
			make1(i, n);
			break;
		}	
	}
	Allmake1(n);
	Allmin(l,n);
}
void min(int s,int h,int n)
{
     
	if(loc[h]==-1&&m[h][n]!=0)
		for (int i = 0; i < N+1; i++)
			m[h][i] -= m[s][i];
}
void Allmin(int s,int n)
{
     
	for (int i = 0; i < N; i++)
		min(s, i, n);
}
void Allreplace()
{
     
	for (int i = 0; i < N; i++)
		Onereplace(i);
}
void cacular(int n)
{
     
	for(int i=0;i<N;i++)
		if (loc[i] == n)
		{
     
			for (int k = 0; k < N; k++)
				if (m[i][k]!=0&&k != n)
					m[i][N] -= m[i][k] * s[k];
			s[n] = m[i][N] / m[i][n];
			break;
		}
}
void Allcacular()
{
     
	for (int i = N - 1; i >= 0; i--)
		cacular(i);
}
void pc()
{
     
	fill(loc, loc + N, -1);
	Allreplace();
	Allcacular();
}
void Cout()
{
     
	for (int i = 0; i < N; i++)
		cout << s[i] << " ";
	cout << endl;
}

int main()
{
     
	pc();
	Cout();
}

你可能感兴趣的:(笔记,c++,线性代数,算法)