高斯消元算法实现(Java)

本文介绍了高斯消元法的算法步骤,包括选择主元、行交换、判断主元、逐行消元、归一化和回代。通过一个具体的例子展示了算法结果,并提供了Java代码实现,使用一维数组处理方程的增广矩阵。

1:高斯消元法算法步骤

1:选择主元;即选择对角元素,保证其为所在列的最大,避免大数除以小数出现溢出,其实是避免其值为0;
2:当前主元不为最大值,交换两行;
3:判断主元是否为0,若是则不是唯一解;
4:逐行消元;
5:对角线元素归一化;
6:回代消除对角线之上的元素。


2:算法结果展示

百度知道上的一道题目,用来测试
图中是原题给出的答案:
原题图片计算结果
下图是算法给出的答案
这里写图片描述
这样看来结果还是很不错的。


3:代码

这个是主方法,主要是使用一维数组实现,对应的方法参数要给出方程增广矩阵的每一行的个数。
内部方法将在后面给出,这个方法可以直接使用。

    /**
     * 
     * @param array 系数矩阵 增广矩阵
     * @param colNum 列向量个数(从第0列开始)
     * @return boolean 是否得出结果
     */
    public  boolean Resolve(float[] array, int colNum){

        //行数
        int rows = array.length / colNum ;


        //逐行选择主元              第 i 行 ,第i列  的元素(i,i)
        for (int i = 0; i < rows; i++) {

            //按列选择主元
            int pivotRow = SelectPivotalElement(array,colNum,i);

            //如果主元不是目前所在的i列,则交换
            if(pivotRow!=i){
                swapCol(array,pivotRow,i,colNum);
            }

            if(array[i*colNum+i]==0){
                System.out.println("不含有唯一解");
                return false ;
            }

            //消元得到上三角
            for (int j = 0; j < colNum; j++) {
                emissElement(array,j,colNum);
            }

        }

        //主元素归一化
        for (int i = 0; i < rows; i++) {
            ElementBack(array,i,colNum);
        }

        //回代消元,从最后一行开始
        for (int i = rows-1; i > 0; i--) {
            backEmiss(array,i,colNum);
        }

        return true ;

    }

用于内部实现的各个方法

    /**
     * 回代消元
     * @param array
     * @param i 第i行之上的开始消除
     * @param colNum 矩阵每一行的个数
     */
    private static void backEmiss(float[] array, int i, int colNum) {

        for (int j = i; j >0; j--) {
            float fractor = array[(j-1)*colNum+i] ;
            array[(j-1)*colNum+i] = 0 ;
            array[j*colNum-1] = array[j*colNum-1] -  array[(i+1)*colNum-1]*fractor ;
        }

    }
    /**
     * 元素归一化处理
     * @param array
     * @param i 第 i 行 归一化处理
     * @param colNum 矩阵列数 ,每行元素个数
     */
    private static void ElementBack(float[] array, int i, int colNum) {

        //每行的长度
        int len = array.length / colNum ;

        float factor = array[i * colNum + i] ;
        for (int j = i * colNum + i; j < (i+1)*colNum; j++) {
            array[j] = array[j] / factor ;
        }

    }
    /**
     * 逐行消元
     * @param array
     * @param i 标示第 i 行的主元
     * @param colNum
     */
    private static void emissElement(float[] array, int i, int colNum) {

        //矩阵行数
        int len = array.length / colNum ;

        //第i+1行开始消元
        for (int j = (i+1); j <len; j++) {
         //int j = 1 ;
            //消元系数
            float index = array[j*colNum+i] / array[i * colNum + i] ;
            int ii = i * colNum + i ;
            for (int k = j*colNum + i; k < (j+1)*colNum  ; k++,ii++) {
                array[k] = array[k] - array[ii]*index ; 
            }

        }


    }
    /**
     * 交换两行
     * @param array
     * @param dist 目标行
     * @param src  原来的行
     * @param colNum 行向量的长度
     */
    private static void swapCol(float[] array, int dist, int src,int colNum) {


        int distance = (dist - src)*colNum ;

        for (int j = src*colNum; j < (src+1)*colNum; j++) {
            float temp = array[j] ;
            array[j] = array[j+distance] ;
            array[j+distance] = temp ;

        }

    }
    /**
     * 
     * @param array
     * @param colNum
     * @param i  第i行的主元
     * @return 主元所在的列
     */
    private static int SelectPivotalElement(float[] array,int colNum,int i) {


        //返回的所选择的主元所在列的索引
        int pivotColIndex = 0 ;

        //中间变量
        float max = 0 ;


        for (int j = i*colNum + i; j < array.length; j+=colNum) {
            if(Math.abs(max)<Math.abs(array[j])){
                max = array[j];
                pivotColIndex = j ;
            }
        }
        //返回主元所在的行
        return pivotColIndex/colNum;
    }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欧阳小伙

您的打赏是我创作的:最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值