zoukankan      html  css  js  c++  java
  • 解N元一次方程组(消元法和克拉默法)

      因课程作业需要, 经常要求解四元一次方程组, 甚至五元一次方程组, 为了避免重复的劳动遂有了写这个求解函数的想法.

      昨天在网上搜了一把, 没有很合适的, 且都是用克拉默法求解的. 所以冲动之下就写了自己的消元法求解函数.

      现把自己写的"消元算法", 以及在网上搜到的"克拉默求解算法" 献上,  很多地方有待改进,  欢迎拍砖.

    • 消元法.

      

     1     /**
    2 * 用消元法求n元一次方程组的解 采用了递归的方法
    3 *
    4 * @param q :
    5 * 方程组的系数矩阵 以二维数组的形式表示
    6 * @return 方程组的解 以数组形式返回
    7    */
    8 public double[] caculate(double[][] q) {
    9 int hang = q.length; // 行数
    10 int shu = q[0].length; // 列数
    11
    12 if (hang == 1) { // 化简到成为一元一次方程的时候
    13 double[] x = { q[0][1] / q[0][0] };
    14 return x;
    15 } else {
    16 double[][] temp = new double[hang - 1][shu - 1]; // 保存消元后的数组
    17
    18        // 分开第一个系数为0 的行
    19 List<double[]> zerorows = new ArrayList<double[]>(); // 第一个系数为0 的行
    20 List<double[]> otherrows = new ArrayList<double[]>();
    21
    22 for (int i = 0; i < hang; i++) {
    23 if (q[i][0] == 0)
    24 zerorows.add(q[i]);
    25 else
    26 otherrows.add(q[i]);
    27 }
    28
    29 for (int i = 0; i < otherrows.size() - 1; i++) {
    30 for (int j = 1; j < shu; j++) {
    31 temp[i][j-1] = otherrows.get(i+1)[0]*otherrows.get(i)[j]
    32 - otherrows.get(i)[0]*otherrows.get(i+1)[j];
    33 }
    34 }
    35 for (int i = 0; i < zerorows.size(); i++) {
    36 for (int j = 1; j < shu; j++) {
    37 temp[i + otherrows.size() - 1][j - 1] = zerorows.get(i)[j];
    38 }
    39 }
    40 double[] result = this.caculate(temp); // 递归,上步简化得到的结果
    41
    42
    43       // 还要先判断 第一个数的系数是否为0
    44 int row = 0;
    45 while (q[row][0] == 0) {
    46 row++;
    47 }
    48
    49 double d = 0.00;
    50 for (int i = 1; i < shu-1; i++)
    51 d += q[row][i] * result[i-1];
    52 double x = (q[row][shu-1] - d) / q[row][0]; //将前面得到的结果 代入 求出当前 未知数
    53
    54 double[] newresult = new double[result.length + 1];
    55 newresult[0] = x;
    56 for (int i = 0; i < result.length; i++) {
    57 newresult[i + 1] = result[i];
    58 }
    59
    60 return newresult;
    61 }
    62
    63 }



    View Code
      1 /**
    2 * @author zouyf 2008-4-7 本程序利用克拉默法则解多元一次方程组
    3 */
    4 public class GetMatrix
    5 {
    6 private double[][] savequot;// 保存变量系数
    7 private double[] constquot;// 保存常量系数
    8 private double[] saveResult;// 保存解的集合
    9
    10 public GetMatrix(double quot[][])
    11 {
    12 int count = quot.length;
    13 savequot = new double[count][count];
    14 constquot = new double[count];
    15 saveResult = new double[count];
    16 int i = 0, j = 0;
    17 for (i = 0; i < count; i++)
    18 {
    19 for (j = 0; j < count; j++)
    20 {
    21 savequot[i][j] = quot[i][j];
    22 }
    23 constquot[i] = quot[i][count];
    24 saveResult[i] = 0;
    25 }
    26 }
    27
    28 private double getMatrixResult(double input[][])// 递归的方法求得某个行列式的值
    29 {
    30 if (input.length == 2)//递归出口,为二阶行列式时,直接返回
    31 {
    32 return input[0][0] * input[1][1] - input[0][1] * input[1][0];
    33 }
    34 else
    35 {
    36 double[] temp = new double[input.length];//存放第一列的系数值
    37 double[][] tempinput = new double[input.length - 1][input.length - 1];
    38 double result = 0;
    39 for (int i = 0; i < input.length; i++)
    40 {
    41 temp[i] = input[i][0];
    42 int m = 0, n = 0;
    43 for (int k = 0; k < input.length; k++)
    44 {
    45 if (k != i)
    46 {
    47 for (m = 0; m < input.length - 1; m++)
    48 {
    49 tempinput[n][m] = input[k][m + 1];//删除当前变量系数所在的行和列,得到减少一阶的新的行列式
    50 }
    51 n++;
    52 }
    53 }
    54 if (i % 2 == 0)// 递归调用,利用代数余子式与相应系数变量的乘积之和得到多阶行列式的值
    55 {
    56 result = result + temp[i] * getMatrixResult(tempinput);
    57 }
    58 else
    59 {
    60 result = result - temp[i] * getMatrixResult(tempinput);
    61 }
    62 }
    63 return result;
    64 }
    65 }
    66
    67 private double[][] getReplaceMatrix(int i)// 用常数系数替换相应的变量系数,得到新的行列式
    68 {
    69 double tempresult[][] = new double[savequot.length][savequot.length];
    70 for (int m = 0; m < savequot.length; m++)
    71 {
    72 for (int n = 0; n < savequot.length; n++)
    73 {
    74 if (i != m)
    75 {
    76 tempresult[n][m] = savequot[n][m];
    77 }
    78 else
    79 {
    80 tempresult[n][i] = constquot[n];// 用常量系数替换当前变量系数
    81 }
    82 }
    83 }
    84 return tempresult;
    85 }
    86
    87 public double[] getResult()
    88 {
    89 double basic = 0;
    90 basic = getMatrixResult(savequot);//得到变量系数行列式的值
    91 if (Math.abs(basic) < 0.00001)
    92 {
    93 System.out.println("it dose not have the queue result!");
    94 return saveResult;
    95 }
    96 double[][] temp = new double[saveResult.length][saveResult.length];
    97 for (int i = 0; i < saveResult.length; i++)
    98 {
    99 temp = getReplaceMatrix(i);
    100 saveResult[i] = getMatrixResult(temp) / basic;
    101 }
    102 return saveResult;
    103 }
    104
    105
    106
    107 public static void main(String[] args)
    108 {
    109 /**
    110 * 测试方程组
    111 * 2a+b-5c+d=8
    112 * a-3b-6d=9
    113 * 2b-c+2d=-5
    114 * a+4b-7c+6d=0
    115 */
    116 double[][] test = { { 2, 1, -5, 1, 8 }, { 1, -3, 0, -6, 9 },
    117 { 0, 2, -1, 2, -5 }, { 1, 4, -7, 6, 0 } };
    118
    119 GetMatrix gm = new GetMatrix(test);
    120 double[] uu = new double[test.length];// 返回结果集
    121 uu = gm.getResult();
    122 for (int i = 0; i < uu.length; i++)
    123 {
    124 System.out.println(uu[i] + ",");
    125 }
    126 }
    127 }
    • 比较

      两个算法比起来, 消元法看起来简洁一点. 

      但是还有一个问题, 第一个算法会出现小数精度的问题, 例如:

     1     public static void main(String[] args) {
    2
    3 double[][] xishu1 = { { 2.0, 4, 1, 8 }, { 4, -2, 2, 0 }, { 4, 1, 0, 6 } };
    4
    5 Caculater c = new Caculater();
    6 double[] res = c.caculate(xishu1);
    7
    8 for (double d : res)
    9 System.out.println(d);
    10 }

      运行的结果是:

    1 1.0999999999999996
    2 1.6
    3 -0.6

      很明显, 第一个解应该是1.1 才是正确的答案.

      小数精度的问题 留到日后解决吧.




  • 相关阅读:
    Linux高并发内核优化-TougheRadius
    Zabbix 4.0 配置邮件报警功能
    Zabbix Agent 4.0 Windows 安装配置
    zabbix4.0前端个性化设置
    zabbix 4.0中文图形界面乱码问题
    Zabbix4.0系统告警“More than 75% used in the configuration cache”
    Zabbix4.0配置SNMP监控
    Zabbix4.0 SNMP安装
    Zabbix4.0添加cisco交换机基本监控步骤
    深入.NET框架
  • 原文地址:https://www.cnblogs.com/danne823/p/2270693.html
Copyright © 2011-2022 走看看