在这里感谢我的学长以及Bowen Young大佬提供了帮助

前言

前几天刚开始学线性代数,于是就想用C++复现一下
本来以为是很简单的,但是后期纠错花了好几个晚上才搞定
毕竟我太菜了
C++源码已上传至GitHub

项目地址

源码

#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 sum(double x[max_n][max_n],int n)
{
    double sum1=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++)
    {
        sum1+=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 sum1;
}

int main()
{
    int n;//阶数
    double x[max_n][max_n];
    cout<<"input n=";
    cin>>n;//定义行列式阶数

    //输入行列式的每一项的值
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            cout<<"input x["<<i<<"]["<<j<<"]=";
            cin>>x[i][j];
        }
    }
    
    
    cout<<"D="<<sum(x,n);
    
    return 0;
}

解析

n阶行列式定义

n阶行列式定义
这里将行列式中的每项视为一个二维数组x[max_n][max_n]
行列式的数组形式
其中在开头定义的常量max_n为本程序所能运算的最大阶数

n阶行列式的定义式

n阶行列式定义式
可以看出:
n阶行列式在运算时由两个部分组成

  • 第一部分是系数,在所选的序列的总逆序数为偶数时取1,奇数为-1
  • 第二部分是所选序列的累乘
    那么在编写程序时也可分成这两项来分别编写
    n阶行列式的构成
    其中,系数k由函数t(int p[N],int n)生成
    累乘部分由函数product(double x[max_n][max_n],int p[N],int n)生成

系数的生成

由于定义中规定不能选中同行同列的项相乘,但由于这个实现起来比较麻烦,所以就将同列的情况所对应系数为0
即:

  • 序列为偶逆序,函数返回1
  • 序列为奇逆序,函数返回-1
  • 序列为同列,函数返回0

累乘的生成

这个没什么好说的,将结果的值先初始化为1,然后从序列p[]中读取每轮所要取第几行第几列的值,然后用for循环实现累乘即可

序列的生成

这个想了很久,后来请教了我计科的学长,用n位n进制来实现:

这是一个n*n的矩阵,每行取一个数,需要遍历每一种结果,因此共有n^n种不同的取法
那么可以由这么一个数表示每行所要取第几列,也就是一个n位长的数,每一轮个位都自增1,逢n进1,直到n^n种情况遍历完为止
这个数的每一位都表示该行取第几列,比如个位数表示第一行取第几位,十位数表示第二位取第几位,n位数表示第n行取第几位
每次先自增1,再由一个for循环嵌套if来判断是否需要进位
为方便,就将这段序列数存储在了数组p[]
并且在此之前需要将数组初始化
这段代码被写在了sum(double x[max_n][max_n],int n)

所遇到的问题

1. 数组索引溢出

定义数组时用的x[max_n][max_n],但是在for循环中所遍历的范围是1-max_n,超出了数组所定义的范围
所以后期调整为遍历0-max_n

2. 乘方的表示

之前写乘方时使用的是n^n,但在C++中^表示异或
正确的方式是在头文件中调用<cmath>,然后使用pow()函数
pow()函数的使用方法:
pow(x,y)表示x的y次方

3. C++环境出错

后来发现所有的错误都排除了,但是还是不能正常输出D的值,但是在学长的电脑上能正常运行的,因此发现是环境问题
将VSCode换为Dev C++后居然就能正常运行了
目前该问题笔者还在研究中

小结

肝这个代码花了我近四天晚上的时间来构思和修改错误
尽管并非作业,但是能用自己所学的C++来实现某项功能还是很有成就感的
也很感谢有大佬在我遇到困难时能出手相助

Last modification:October 7, 2022
如果觉得我的文章对你有用,请随意赞赏