zoukankan      html  css  js  c++  java
  • 线性代数辅助程序

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

    题目是这样的

    题目
    请开发一个《线性代数》课程学习辅助软件,自主设计界面,现实以下功能:
    (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,相信在计算数学中这是最理想的结果了。

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



  • 相关阅读:
    c++ 启发式搜索解决八数码问题
    基于linux或windows的c/s的循环服务器求一元二次方程的根
    基于linux或windows平台上的c/s简单通信
    第七章总结
    第六章总结
    第五章总结
    第四章总结
    第一章总结
    第三章总结
    第二章总结
  • 原文地址:https://www.cnblogs.com/--lr/p/10015030.html
Copyright © 2011-2022 走看看