今天让我们来用c解线性方程组。
手动解线性方程组有两种方法。
1.通过消元求解
2.通过矩阵行列式等来求解
我们现在要用c语言来实现用行列式求解线性方程组。在求解之前我们首先要学习行列式相关知识,如果不了解行列式请先去百度行列式进行学习,记得回来哦~
可以发现行列式的数字排法很像二维数组的排法,于是我们用二维数组保存行列式内容。所以我们只需要把输入的数据存入二维数组内。
因为数组的大小在定义的时候必须是确定的,而我们可能要算二元一次方程组,我们有四个数据,也可能是三元的我们有九个数据,于是二元的需要定义一个a[2][2],三元的我们要定义一个a[3][3]。这不是一个确定的数,所以我们要才用一种特殊的方式(动态内存分配)。这样就能产生一个动态的数组。
代码如下:
//从输入的数据中存到数组内
double* getArrFromDet(int n)
{
double num;
double* p = (double*)calloc(1, sizeof(double) * n * n);
if (!p)return -1;
int i = 0;
while (n * n != i)
{
scanf("%lf", &num);
*(p + i) = num;
i++;
}
return p;
}
现在我们剩下的问题就是计算数组里面的行列式的值。
我们学过计算行列式有一种方法,叫做拉普拉斯定理。拉普拉斯定理,计算降阶行列式的一种方法。该定理断言:在n阶行列式D=|aij| 中,任意取定k行(列),1≤k≤n-1,由这k行(列)的元素所构成的一切k阶子式与其代数余子式的乘积的和等于行列式D的值。此展式称为拉普拉斯展式。
于是我们就运用这个定理,我们运用第一行的各元素乘以对于的各元素的代数余子式。代数余子式又是一个行列式继续用这个方法,一直到最后只剩下一个就返还这个的值。这像不像是个递归,那我们就用递归来解决这个问题吧
哦~对了好像没告诉你们代数余子式怎么求。现在我们来讲一讲他的求法。
只需要把选定的这个元素的行,和列全部去除,组成的行列式就是余子式,然后代数余子式就是有±号,比如说在第1行第1列的元素的代数余子式就是1×余子式,而第1行第2列的元素就是-1×余子式,是不是能发现什么规律,就是(-1)∧(行+列)×行列式就可以了。好了这个懂了
就来看代码吧。
递归结束条件,只剩下一个元素在行列式中。
//将数组进行行列计算
double calDet(double *arr,int n)
{
int i = 0;
double sum = 0;
if (n == 1)
{
return *arr;
}
else
{
while (i < n)
{
double* arrTemp = (double*)calloc(1, sizeof(double) * (n - 1) * (n - 1));
double* temp = arrTemp;
//去除正在递归的该行列的
for (int k =1; k < n; k++)
{
for (int j = 0; j < n; j++)
{
if (j != i)
{
*temp = *((arr + k * n) + j);
temp++;
}
}
}
sum += pow(-1,i)*(*(arr + i) * calDet(arrTemp, n - 1));//递归调用
i++;
}
}
return sum;
}
现在我们会求行列式了,那问题只剩下一个了:计算多个行列式的值并保存下来然后再运用克拉默法则运算出方程组的解。具体代码如下:
//求解线性方程组
void solveEqu(int n)
{
double value[127] = { 0 };
//获取d的值
printf("d=");
value[0] = calDet(getArrFromDet(n), n);
int i = 1;
while (i != n + 1)
{
printf("d%d=", i);
value[i] = calDet(getArrFromDet(n), n);
i++;
}
//输出方程的解
i = 1;
while (i != n + 1)
{
if (value[0] == 0 && value[i] != 0)
{
printf("方程无解");
break;
}
else
{
printf("x%d = %lf\n", i, value[i] / value[0]);
i++;
}
}
}
这样我们就能解出一个线性方程组。
接下来让我们看看这个简单的主函数把
int main()
{
int n;
printf("输入方程组的元数");
scanf("%d", &n);
solveEqu(n);
while (1);
return 0;
}
就是如此简单,学废了吗