【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个位置储存方程结果)中;
在这里插入图片描述
计算的数据结果我们可以在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<iostream>
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();
}
  • 20
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
在C语言中,可以使用高斯-约旦消元法(Gauss-Jordan elimination)来解多元方程。 步骤如下: 1. 将多元方程组转化为增广矩阵(augmented matrix)形式,即将系数矩阵和常数矩阵合并成一个矩阵。 2. 对增广矩阵进行初等行变换(elementary row operations),使得系数矩阵变为上三角矩阵(upper triangular matrix)。 3. 对上三角矩阵进行回带求解(back substitution),求出未知数的值。 下面是C语言代码示例: ```c #include <stdio.h> #define N 3 // 未知数的个数 #define EPS 1e-10 // 用于判断浮点数是否为0的阈值 void gauss_jordan(double a[N][N+1]) { int i, j, k; for (i = 0; i < N; i++) { // 找到绝对值最大的一行 int pivot = i; for (j = i+1; j < N; j++) { if (fabs(a[j][i]) > fabs(a[pivot][i])) pivot = j; } // 交换当前行和绝对值最大的一行 if (i != pivot) { for (j = 0; j < N+1; j++) { double tmp = a[i][j]; a[i][j] = a[pivot][j]; a[pivot][j] = tmp; } } // 将当前行的第i个元素变为1 double div = a[i][i]; for (j = i; j < N+1; j++) a[i][j] /= div; // 利用当前行将其它行的第i个元素消去 for (j = 0; j < N; j++) { if (i != j) { double mul = a[j][i]; for (k = i; k < N+1; k++) a[j][k] -= a[i][k] * mul; } } } } int main() { double a[N][N+1] = {{2, 1, -1, 8}, {-3, -1, 2, -11}, {-2, 1, 2, -3}}; gauss_jordan(a); int i, j; for (i = 0; i < N; i++) { for (j = 0; j < N+1; j++) { if (fabs(a[i][j]) < EPS) a[i][j] = 0; printf("%.2f ", a[i][j]); } printf("\n"); } return 0; } ``` 该代码解决了以下方程组: $$ \begin{cases} 2x_1+x_2-x_3=8\\ -3x_1-x_2+2x_3=-11\\ -2x_1+x_2+2x_3=-3 \end{cases} $$ 输出的解为: ``` 1.00 0.00 0.00 2.00 -0.00 1.00 0.00 3.00 0.00 0.00 1.00 -1.00 ``` 即 $x_1=2, x_2=3, x_3=-1$。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值