列主元消去法&全主元消去法——Java实现

36 篇文章 0 订阅

1、列主元消去法

pivot.column.ColumnPivot 类:通过构造方法传入增广矩阵,用 getRoot() 方法获取方程组的根。

test.Test 类:用于输入数据。测试 pivot.column.ColumnPivot 的功能。(文末有测试数据)

本文使用的列选主元消去法的计算过程参考 列主元消去法『百度百科』。

代码如下:

package pivot.column;

import java.util.Arrays;

// 列主元消去法
public class ColumnPivot {

	private double[][] matrix;// 增广矩阵
	private int n;// 系数矩阵的阶数

	// 参数为增广矩阵
	public ColumnPivot(int[][] matrix) {
		n = matrix.length;// 系数矩阵的阶
		this.matrix = new double[n][n + 1];
		for (int i = 0; i < n; ++i) {
			for (int j = 0; j <= n; ++j) {
				this.matrix[i][j] = matrix[i][j];// 数据类型转换
			}
		}
	}

	// 参数为增广矩阵
	public ColumnPivot(double[][] matrix) {
		n = matrix.length;// 系数矩阵的阶
		this.matrix = new double[n][n + 1];
		for (int i = 0; i < n; ++i) {// 备份
			this.matrix[i] = Arrays.copyOf(matrix[i], n + 1);
		}
	}

	// 获取方程组的根
	public double[] getRoot() {
		for (int k = 0; k < n - 1; ++k) {
			int i = columnPivoting(k);// 列选主元
			if (matrix[i][k] == 0) {
				return new double[0];// 无解
			}
			if (i != k) {
				lineSwitch(k, i);// 行交换
			}
			elimination(k);// 消元
		}
		return backSubstitution();// 回代求根并返回根
	}

	// 选第k列的主元
	private int columnPivoting(int k) {
		double maxVal = Math.abs(matrix[k][k]);
		int maxRow = k;
		for (int i = k + 1; i < n; ++i) {// 查找值最大的行下标
			double val = Math.abs(matrix[i][k]);
			if (val > maxVal) {
				maxVal = val;
				maxRow = i;
			}
		}
		return maxRow;// 返回行下标
	}

	// a[l1][j]和a[l2][j]交换,j=l1,l1+1,...,n
	private void lineSwitch(int l1, int l2) {// l1 < l2
		for (int j = l1; j <= n; ++j) {
			double temp = matrix[l1][j];
			matrix[l1][j] = matrix[l2][j];
			matrix[l2][j] = temp;
		}
	}

	// 消元
	private void elimination(int k) {
		for (int i = k + 1; i < n; ++i) {
			matrix[i][k] /= matrix[k][k];// 倍数
			for (int j = k + 1; j <= n; ++j) {
				matrix[i][j] -= matrix[i][k] * matrix[k][j];
			}
		}
	}

	// 回代求根
	private double[] backSubstitution() {
		double[] root = new double[n];
		for (int i = n - 1; i >= 0; --i) {
			for (int j = i + 1; j < n; ++j) {
				matrix[i][n] -= matrix[i][j] * root[j];
			}
			root[i] = matrix[i][n] / matrix[i][i];
		}
		return root;
	}

}
package test;

import java.util.Scanner;
import pivot.column.ColumnPivot;

// 测试类
public class Test {

	public static void main(String[] args) {
		// 输入增广矩阵
		Scanner sc = new Scanner(System.in);
		int order = sc.nextInt();
		int[][] matrix = new int[order][order + 1];
		for (int i = 0; i < order; ++i) {
			for (int j = 0; j <= order; ++j) {
				matrix[i][j] = sc.nextInt();
			}
		}
		sc.close();
		
		ColumnPivot cp = new ColumnPivot(matrix);// 创建对象
		double[] root = cp.getRoot();// 获取方程组的根
		
		// 输出结果
		if (root.length == 0) {
			System.err.println("方程组无解!");
		} else {
			for (int i = 0; i < root.length; ++i) {
				System.out.print("X" + (i + 1) + " =");
				System.out.printf("%6.2f\n", root[i]);
			}
		}
	}

}

2、全主元消去法

pivot.complete.CompletePivot 类用于全主元计算方程组的根。用 getRoot() 方法获取根。

test.Test 类用于输入数据测试 pivot.complete.CompletePivot 类的功能。(文末有测试数据)

相对于列选主元,全主元需要进行必要的列交换,以及记录根的位置。其他基本相似。

代码如下:

package pivot.complete;

import java.util.Arrays;

// 全主元消去法
public class CompletePivot {

	private double[][] matrix;// 增广矩阵
	private int n;// 系数矩阵的阶数
	private int[] rootOrder;// 保存根的顺序,因为列交换会改变根的顺序

	// 参数为增广矩阵
	public CompletePivot(int[][] matrix) {
		n = matrix.length;// 系数矩阵的阶
		this.matrix = new double[n][n + 1];
		for (int i = 0; i < n; ++i) {
			for (int j = 0; j <= n; ++j) {
				this.matrix[i][j] = matrix[i][j];// 数据类型转换
			}
		}
	}

	// 参数为增广矩阵
	public CompletePivot(double[][] matrix) {
		n = matrix.length;// 系数矩阵的阶
		this.matrix = new double[n][n + 1];
		for (int i = 0; i < n; ++i) {// 备份
			this.matrix[i] = Arrays.copyOf(matrix[i], n + 1);
		}
	}

	// 获取方程组的根
	public double[] getRoot() {
		rootOrder = new int[n];
		for (int i = 0; i < n; ++i) {
			rootOrder[i] = i;// 初始化根的顺序
		}
		
		for (int k = 0; k < n - 1; ++k) {
			int[] coords = completePivoting(k);// 全选主元获取主元坐标
			if (matrix[coords[0]][coords[1]] == 0) {
				return new double[0];// 无解
			}
			if (coords[0] != k) {
				lineSwitch(k, coords[0]);// 行交换
			}
			if (coords[1] != k) {
				columnSwitch(k, coords[1]);// 列交换
			}
			elimination(k);// 消元
		}
		return backSubstitution();// 回代求根并返回根
	}

	// 全选主元
	private int[] completePivoting(int k) {
		double maxVal = Math.abs(matrix[k][k]);
		int[] coords = { k, k };// 主元坐标
		for (int i = k; i < n; ++i) {
			for (int j = k; j < n; ++j) {
				double val = Math.abs(matrix[i][j]);
				if (val > maxVal) {
					maxVal = val;
					coords[0] = i;
					coords[1] = j;
				}
			}
		}
		return coords;
	}

	// a[l1][j]和a[l2][j]交换,j=l1,l1+1,...,n
	private void lineSwitch(int l1, int l2) {// l1 < l2
		for (int j = l1; j <= n; ++j) {
			double temp = matrix[l1][j];
			matrix[l1][j] = matrix[l2][j];
			matrix[l2][j] = temp;
		}
	}

	// a[i][c1]和a[i][c2]交换,i=c1,c1+1,...,n-1
	private void columnSwitch(int c1, int c2) {// c1 < c2
		for (int i = 0; i < n; ++i) {// 整列都要交换!!!
			double temp = matrix[i][c1];
			matrix[i][c1] = matrix[i][c2];
			matrix[i][c2] = temp;
		}
		// 交换根的顺序
		int temp = rootOrder[c1];
		rootOrder[c1] = rootOrder[c2];
		rootOrder[c2] = temp;
	}

	// 消元
	private void elimination(int k) {
		for (int i = k + 1; i < n; ++i) {
			matrix[i][k] /= matrix[k][k];// 倍数
			for (int j = k + 1; j <= n; ++j) {
				matrix[i][j] -= matrix[i][k] * matrix[k][j];
			}
		}
	}

	// 回代求根,注意rootOrder的使用,多体会
	private double[] backSubstitution() {
		double[] root = new double[n];
		for (int i = n - 1; i >= 0; --i) {
			for (int j = n - 1; j > i; --j) {
				matrix[i][n] -= matrix[i][j] * root[rootOrder[j]];
			}
			root[rootOrder[i]] = matrix[i][n] / matrix[i][i];
		}
		return root;
	}

}
package test;

import java.util.Scanner;
import pivot.complete.CompletePivot;

// 测试类
public class Test {

	public static void main(String[] args) {
		// 输入增广矩阵
		Scanner sc = new Scanner(System.in);
		int order = sc.nextInt();
		int[][] matrix = new int[order][order + 1];
		for (int i = 0; i < order; ++i) {
			for (int j = 0; j <= order; ++j) {
				matrix[i][j] = sc.nextInt();
			}
		}
		sc.close();

		CompletePivot cp = new CompletePivot(matrix);
		double[] root = cp.getRoot();
		
		// 输出结果
		if (root.length == 0) {
			System.err.println("方程组无解!");
		} else {
			for (int i = 0; i < root.length; ++i) {
				System.out.print("X" + (i + 1) + " =");
				System.out.printf("%6.2f\n", root[i]);
			}
		}
	}

}

3、测试数据

测试数据1:

4
  2  10   0  -3  10
 -3  -4 -12  13   5
  1   2   3  -4  -2
  4  14   9 -13   7
X1 =  1.00
X2 =  2.00
X3 =  3.00
X4 =  4.00

测试数据2:

3
 1  2  3 10
 4  3  1 19
 2  5  2 18
X1 =  3.00
X2 =  2.00
X3 =  1.00

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值