克拉默法则(Cramer's law)是线性代数中的一条定理,用行列式来计算出线性等式组中的所有解,被用于计算n元一次方程
前言
近期线性代数学习到了克拉默法则,结合前文使用C++实现n阶行列式的计算所写代码,可以实现解n元一阶方程的目的
项目地址
代码
本次代码分为主程序main.cpp
和子程序det.cpp
两部分,主程序主要负责数值的输入和输出,子程序负责计算行列式
main.cpp
#include <iostream>
#include "det.cpp"//导入det.cpp子程序文件
#define MAX 30//最大阶数
//生成临时数组c,从a导入数值,并将c[][t]赋b的值
double calc(double a[MAX][MAX],double b[MAX],int n,int t)
{
double c[MAX][MAX];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(j==t)
c[i][j]=b[i];
else
c[i][j]=a[i][j];
}
}
return det(c,n);//调用子程序的函数计算并返回结果
}
int main() {
double a[MAX][MAX];//定义每项前系数
double b[MAX];//定义等号右边的数
int n;//定义阶数
cout<<"Input n=";
cin>>n;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cout<<"a["<<i<<"]["<<j<<"]=";
cin>>a[i][j];
}
cout<<"b["<<i<<"]=";
cin>>b[i];
}
for(int t=0;t<n;t++)
{
cout<<"x["<<t<<"]="<<calc(a,b,n,t)/det(a,n)<<endl;//即x=Di/D
}
return 0;
}
det.cpp
#include <iostream>
#include <cmath>
#define N 900//比n^n大即可
#define max_n 30//最高可算多少阶行列式
using namespace std;
//计算每项前系数
int t(int p[N],int n)
{
int c=0;//定义逆序数计数器
for(int i=0;i<n-1;i++)
{
for(int j=i+1;j<n;j++)
{
if(p[i]>p[j])
c++;//出现逆序则自增1
else if(p[i]==p[j])
return 0;//出现同列情况将系数变为0
}
}
if(c%2==0)
return 1;//偶逆序数返回1
else
return -1;//奇逆序数返回-1
}
//计算系数外每项的乘积
double product(double x[max_n][max_n],int p[N],int n)
{
double pdt=1;//乘积初始化为1
for(int i=0;i<n;i++)
{
pdt*=x[i][p[i]];
}
return pdt;//返回本次序列数所对应的乘积
}
double det(double x[max_n][max_n],int n)
{
double sum=0;//初始化结果为0
int p[N];//定义序列数,从p[1]开始每一位的值对应取x[][]中每行的第几列
for(int i=0;i<N;i++)
{
p[i]=0;//初始化
}
for(int i=0;i<pow(n,n);i++)
{
sum+=t(p,n)*product(x,p,n);
//开始生成序列数
p[0]++;
for(int j=0;j<n;j++)
{
if(p[j]==n)
{
p[j]=0;
p[j+1]++;
}
}
}
return sum;
}
解析
行列式的计算
有关行列式相关代码,此处不作解析,详见前文使用C++实现n阶行列式的计算
克拉默法则
$x_i=\frac{D_i}{D}$
系数行列式D的值由数组a[MAX][MAX]
存储,等号右边数值由数组b[MAX]
存储
下标i
由for
循环遍历,i
的值会被传递给子函数`calc()
在子函数calc()
中,会复制a[][]
的值给临时数组c[][]
但在第i
列会赋b[i]
的值以替换