标签:误差 lse 操作 targe c++ 大赛 reg 过程 说明文档
参加了一个程序设计大赛,有点数学建模的模式,差不多是校级的,而且看之前的题目都是比较简单,有的就是我们的实验题或者课设题目,所以还是想水一水的(万恶之源***)
题目是这样的
题目 请开发一个《线性代数》课程学习辅助软件,自主设计界面,现实以下功能: (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("请输入一个整数表示矩阵的阶\n"); 2 scanf("%d",&n); 3 printf("请输入矩阵\n"); 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("矩阵的行列式为\n"); 47 if(flag == 0) 48 { 49 printf("0\n"); 50 } 51 else if(flag == -1){ 52 temp = -temp; 53 cout<<temp<<endl; 54 } 55 else 56 { 57 cout<<temp<<endl; 58 } 59 printf("\n");
核心算法就在这了,哎,气的我肝疼,比嘲讽我的帅气更令我桑心就是讽刺我的代码了。。。
基本思路就是将矩阵转化成上三角行列式,然后对角线乘起来就行了,怕老师看不懂这个算法,我还写了详细的注释。
正常点的初等行变换转换成上三角都要与某一行作运算,大多数时候都是将某一行+-上参考行的几分之几,这里涉及分数,所以就会产生误差,于是这就用到了辗转相除法(没想到辗转相除法不止可以求GCD还能这样用,见识了)
这是收获最大的一个程序了,因为这样算出来的行列式误差为0,相信在计算数学中这是最理想的结果了。
然而我已无力吐槽。。。各位大佬,告辞了您嘞!
微信公众号搜索 田长宏
后台回复 线代程序即可获取源码,你想要的资源我都有 (#^.^#)
标签:误差 lse 操作 targe c++ 大赛 reg 过程 说明文档
原文地址:https://www.cnblogs.com/--lr/p/10015030.html