线性代数辅助程序

参加了一个程序设计大赛,有点数学建模的模式,差不多是校级的,而且看之前的题目都是比较简单,有的就是我们的实验题或者课设题目,所以还是想水一水的(万恶之源***)

题目是这样的

题目
请开发一个《线性代数》课程学习辅助软件,自主设计界面,现实以下功能:
(1)计算两个矩阵的加法、减法、乘法功能
(2)求方阵的行列式
(3)求方阵的逆矩阵

具体要求如下:
(1)界面简洁,操作简便。
(2)程序源代码格式正确,符合编码规范(编程语言不限),有适当注释。
(3)编写程序设计文档。
(4)编写程序安装、执行说明文档。 

看题目比较好实现,而且当初学线代的时候我就考虑过实现求行列式的想法,但是老师说的是行列式超过多少阶就不好算了,然后毕竟学软件的,编程实现一下起步美滋滋,然后就参加了、然后就参加了、然后就参加了!!!

最后老师给了40分   满分100分  看到结果真的是一脸懵逼,我真的不理解老师是怎么评的分(一个大大的问号脸)


刚开始就决定用C++写,1、我比较熟悉,实现起来简单2、不用安装各种插件,使用起来也很方便3、大部分大学生都是学过C的,所以C++很多代码大家也都能看得懂

时间给了3天好像,第一天晚上搭了整体框架,第二天实现主要功能,第三天细节优化

矩阵的加法、减法和乘法直接裸敲的。行列式刚开始都忘了啥是行列式了,然后就开始百度学习了,O(∩_∩)O哈哈~  

行列式、伴随矩阵、逆矩阵还有初等行变换,上三角矩阵,完美的印证了我都给忘了,但是看了一下也是可以很快的想起来,知道了怎么回事了就开始写代码,刚开始肯定是没有思路的,不知道怎么实现求矩阵行列式,然后就找相关播客,找到一篇实现既简单还看着比较高大上的博客 传送门 


//计算矩阵的行列式
//将行列式转换为上三角行列式计算起来方便
//考虑到转换过程中可能会遇到分数的计算,从而产生误差
//决定使用求最大公约数中的辗转相除法进行化简
//求两个数的最大公约数时运用辗转相除法一定可以化简为
//一个整数和0的形式,而且过程中全是整数的运算
//下面简单证明辗转相除法
// 设 m = n*a+b; 求证 gcd(m,n) = gcd(n,b);
// 设 x 为 m和n的最大公约数 则m%x = 0 && n%x = 0
//因此n*a%x = 0 从而(m-n*a)% x = 0; m - n*a = b b%x = 0
//所以gcd(n,b) = x

 1     printf("请输入一个整数表示矩阵的阶
");
 2     scanf("%d",&n);
 3     printf("请输入矩阵
");
 4     for(int i = 1; i <= n; i++)
 5     {
 6         for(int j = 1; j <= n; j++)
 7         {
 8             scanf("%d",&answer[i][j]);
 9         }
10     }
11     for(int i = 1; i <= n; i++)//i 表示行
12     {
13         for(int j = i+1; j <= n; j++)//j表示列
14         {
15             int x = i,y = j;   //x,y表示相互运算的两行
16             while(answer[y][i])//行列互换表示与主对角线对称的元素
17             {
18                 //ans 表示商
19                 long long ans = answer[x][i]/answer[y][i];
20                 for(int k = i; k <= n; k++)
21                 {
22                     //每一次都交换第x行
23                     answer[x][k] = answer[x][k] - answer[y][k]*ans;
24                 }
25                 swap(x,y);
26             }
27             //最后没有交换成原始的模样说明
28             //奇数次交换,整个行列式要取反
29             if(x!=i)
30             {
31                 for(int k = i; k <= n; k++)
32                 {
33                     swap(answer[x][k],answer[y][k]);
34                 }
35                 flag*=-1;
36             }
37         }
38         if(answer[i][i] == 0)
39         {
40             flag = 0;
41             break;
42         }
43         temp *= answer[i][i];
44     }
45     SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);// 控制颜色的,不用看
46     printf("矩阵的行列式为
");
47     if(flag == 0)
48     {
49         printf("0
");
50     }
51     else if(flag == -1){
52         temp = -temp;
53         cout<<temp<<endl;
54     }
55     else
56     {
57         cout<<temp<<endl;
58     }
59     printf("
");

核心算法就在这了,哎,气的我肝疼,比吐槽我的帅气更令我桑心就是讽刺我的代码了。。。

基本思路就是将矩阵转化成上三角行列式,然后对角线乘起来就行了,怕老师看不懂这个算法,我还写了详细的注释。

正常点的初等行变换转换成上三角都要与某一行作运算,大多数时候都是将某一行+-上参考行的几分之几,这里涉及分数,所以就会产生误差,于是这就用到了辗转相除法(没想到辗转相除法不止可以求GCD还能这样用,见识了)

这是收获最大的一个程序了,因为这样算出来的行列式误差为0,相信在计算数学中这是最理想的结果了。

然而我已无力吐槽。。。各位大佬,告辞了您嘞!



原文地址:https://www.cnblogs.com/--lr/p/10015030.html