数值分析

  1. 解线性方程组

解线性方程组

关于数值分析的相关实验源码可以访问我的github获取: JavaOs467/project at main · os467/JavaOs467 (github.com)

下面采用的是消主元法,也是我们通常最常用的解线性方程组方法,本质上就是带入消元法。

package project.lab5;


/**
 * 消主元法
 */
public class Miss {


  /*  private float[][] matrix = {
            {10F,-1F,-2F,7.2F},
            {-1F,10F,-2F,8.3F},
            {-1F,-1F,5F,4.2F}
    };*/

 /*   private float[][] matrix =
            {
                    {-3F,2F,6F,4F},
                    {10F,-7F,0F,7F},
                    {5F,-1F,5F,6F}
            };*/

    /*private float[][] matrix =
            {
                    {2F,3F,5F,5F},
                    {3F,4F,7F,6F},
                    {1F,3F,3F,5F}
            };*/

    /*private float[][] matrix =
            {
                    {6F,18F,-15F,-17F,14F,-17F,24F},
                    {-4F,-19F,11F,12F,-4F,15F,12F},
                    {-7F,-2F,-22F,6F,-13F,21F,13F},
                    {-24F,-10F,-21F,10F,8F,-11F,24F},
                    {12F,-22F,9F,8F,-3F,-4F,24F},
                    {-5F,-18F,13F,4F,22F,15F,3F}
            };*/
    private float[][] matrix =
            {
                    {226F,18F,-15F,-17F,14F,-17F,24F},
                    {-4F,201F,11F,12F,-4F,15F,12F},
                    {-7F,-2F,-198F,6F,-13F,21F,13F},
                    {-24F,-10F,-21F,230F,8F,-11F,24F},
                    {12F,-22F,9F,8F,217F,-4F,24F},
                    {-5F,-18F,13F,4F,22F,235F,3F}
            };

    //行数量
    private int r;
    //列数量
    private int c;
    //已扫描行
    private int pass = 0;
    //原始矩阵副本
    private float[][] matrixOrigin;
    //解集
    private float[] x;

    public static void main(String[] args) {
        Miss guss = new Miss();
        guss.d();
    }

    private void d() {

        //检查矩阵合法性并初始化参数
        if (checkMatrix()) return;

        //打印矩阵
        printMatrix();

        //先记录以下原矩阵
        matrixOrigin = new float[r][c];

        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                matrixOrigin[i][j] = matrix[i][j];
            }
        }

        //先消去x1,然后x2,最后解出x3,x2,x1
        for (int i = 0; i < c - 2; i++) {
            //将系数最大的行选出
            Float max = null;
            Integer maxRow = null;
            //比大小找最大主元行
            for (int j = 0; j < r; j++) {
                if (max == null || Math.abs(matrix[j][i]) > Math.abs(max)){
                    max = matrix[j][i];
                    maxRow = j;
                }
            }
            //交换已扫描行最大行
            exchangeRow(pass,maxRow);
            maxRow = pass;
            pass++;
            //maxRow行的系数更新
            for (int j = 0; j < c; j++) {
                matrix[maxRow][j] /= max;
            }

            //更新其它行的系数值
            for (int j = pass; j < r; j++) {
                float a = matrix[j][i];
                //消去a
                matrix[j][i] = 0;
                //更改每行b值
                matrix[j][c-1] += -a * matrix[maxRow][c-1];
                //更改每行其它系数值
                for (int k = 0; k < c - 1; k++) {
                    if (k != i){
                        matrix[j][k] += a * -matrix[maxRow][k];
                    }
                }
            }

        }

        //开始回解
        for (int i = r-1; i >= 0 ; i--) {
            float sumDiv = 0;
            for (int j = 0; j < c - 1; j++) {
                sumDiv+=matrix[i][j];
            }
            x[i] = matrix[i][c-1]/sumDiv;
            //消去其它行的未知数
            for (int j = i - 1; j >= 0; j--) {
                //更新b值
                matrix[j][c-1] -= matrix[j][i] * x[i];
                //系数置0
                matrix[j][i] = 0;
            }
        }

        //打印结果
        printAns();
    }

    private void exchangeRow(int pass, Integer maxRow) {
        if (pass == maxRow) return;
        for (int i = 0; i < c; i++) {
            matrix[maxRow][i] += matrix[pass][i];
            matrix[pass][i] = matrix[maxRow][i] - matrix[pass][i];
            matrix[maxRow][i] -= matrix[pass][i];
        }
    }

    private void printAns() {
        float[] lrMiss = new float[r];

        //计算左边 - 右边
        for (int i = 0; i < r; i++) {
            float sum = 0;
            for (int j = 0; j < c - 1; j++) {
                sum += matrixOrigin[i][j] * x[j];
            }
            lrMiss[i] = sum - matrixOrigin[i][c-1];
        }

        int padding = 20;
        for (int i = 0; i < r; i++) {
            String ansX = "x"+(i+1)+" = "+ (Math.abs(x[i]) < 0.00001F ? 0 : x[i]);
            System.out.print(ansX);
            for (int j = 0; j < padding - ansX.length(); j++) {
                System.out.print(" ");
            }
            System.out.print("|");
            System.out.println("\t\t 左边 - 右边 = "+lrMiss[i]);
        }
    }

    private void printMatrix() {
        System.out.println("解目标方程组:");
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c - 1; j++) {
                if (j != 0){
                    System.out.print(Math.abs(matrix[i][j])+"x"+(j+1)+"\t");
                }else {
                    System.out.print(matrix[i][j]+"x"+(j+1)+"\t");
                }
                if (j != c-2){
                    if (matrix[i][j+1] > 0){
                        System.out.print("+\t");
                    }else {
                        System.out.print("-\t");
                    }
                }

            }
            System.out.println(" = \t\t"+matrix[i][c-1]);
        }
        System.out.println("\n\n");
    }

    private boolean checkMatrix() {
        r = matrix.length;
        if (r == 0) return true;
        c = matrix[0].length;
        x = new float[c-1];
        return false;
    }


}

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件至 1300452403@qq.com

文章标题:数值分析

字数:985

本文作者:Os467

发布时间:2023-09-26, 14:21:20

最后更新:2024-02-03, 04:28:02

原始链接:https://os467.github.io/2023/09/26/%E6%95%B0%E5%80%BC%E5%88%86%E6%9E%90/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

×

喜欢就点赞,疼爱就打赏