Gauss消去法和主元素消去法的Java实现


本人是个新手,写下博客用于自我复习、自我总结。
如有错误之处,请各位大佬指出。


题目:
在这里插入图片描述
分别用Gauss消去法和主元素消去法解方程组

(要求用具有舍入的4位数进行运算),并将所得结果与具有四位有较数字的准确解进行比较。


import java.math.BigDecimal;
import java.util.Scanner;

//@author zsx
//例题输入数据:
//0.001 2.000 3.000 1.000 -1.000 3.712 4.623 2.000 -2.000 1.072 5.643 3.000
//本程序只能解决指定问题(直接法解方程组)
public class DirectMethod {
	public static void main(String args[]) {
		
		int number=0; //记录阶数
		double equation[][];//记录方程组的矩阵
		
		System.out.println("输入阶数n:(n元一次方程组)");
		Scanner sc = new Scanner(System.in); 
        number = sc.nextInt(); 
        equation=new double[number][number+1];//根据阶数建立方程组
      
        try {
        	System.out.println("请按行列输入各未知数的系数以及常数项(如果未知数前系数为0,也请描述出来)");
            System.out.println("输入顺序:x1,x2,x3,常数项(放在等号右边的常数项)");
            for(int x=0;x<number;x++) {  //向方程组中加入数据
          	  for(int y=0;y<number+1;y++) {
                  equation[x][y] = sc.nextDouble();
              }
            }     
        }catch(Exception e) {
        	System.out.println("输入的数据数量有误,请仔细检查");
        }
      
		Gauss(equation,number); //调用Gauss消去法
		mainElementsElimination(equation,number);//调用主元素消去法
		
	}
	
	//Gauss消去法
	public static void Gauss(double equation[][],int n) {
		double mul=0;//求上三角矩阵中的倍数关系
		double result=0;//记录x1,x2,x3..xn的结果

		double X[]= new double[n+1]; //用数组来记录x1,x2,x3..xn的结果

		//求上三角矩阵
		for(int x=0;x<n-1;x++) {
			for(int y=x;y<n-1;y++) {
				//记录所求两行的倍数关系
				mul=-(equation[y+1][x]/equation[x][x]);
				for(int a=x;a<n+1;a++) {
					//更新矩阵数据
					equation[y+1][a]=equation[y+1][a]+equation[x][a]*mul;
				}
			}
		} 
		
		System.out.println("Gauss消去法计算结果为:");
		//解出结果
		for(int x=n-1;x>=0;x--) {
			//每次循环都让result等于常数项
			result=equation[x][n];
			for(int y=n;y>x;y--) {
				if(y-1==x) { //如果运行到了 未知数*系数 = 常数项 的时候
					result=result/equation[x][y-1];
				}
				else {  //如果运行到了  未知数*系数 + 已求解的未知数*系数 = 常数项 的时候
					result=result-(equation[x][y-1]*X[y-1]);
				}
			}
			X[x]=result; //记录求解出来的x值
			//为方便浏览,以及根据题中要求,选择保留5位小数
			BigDecimal b = new BigDecimal(result);
			result = b.setScale(5, BigDecimal.ROUND_HALF_UP).doubleValue(); 
			//去掉小数中的科学计数法形式:
			BigDecimal bg=new BigDecimal(result+""); 
			System.out.println("x"+(x+1)+"="+bg);
		}
	}
	
	//主元素消去法
	public static void mainElementsElimination(double equation[][],int n) {
		double mul=0;//求上三角矩阵中的倍数关系
		double result=0;//记录x1,x2,x3..xn的结果
		double dbChange=0;//用于给矩阵中的数据  交换数据
		int inChange=0;//用于给x1,x2,x3的位置  交换数据
		int maxX=1,maxY=1; //记录最大的横纵坐标
		
		double X[]= new double[n+1]; //用数组来记录x1,x2,x3..xn的结果
		int num[]=new int[n+1]; //用来记录调换顺序后的x
		//默认顺序 x1,x2,x3....
		for(int a=0;a<n;a++){
			num[a]=a+1;
		}
		
		//给矩阵重新排序
		for(int x=0;x<n-1;x++) {
			//重新排序之找到目前区域矩阵中最大的横纵坐标
			for(int x1=x;x1<n;x1++){
				for(int y1=x;y1<n;y1++){
					//每第一次进入循环,先默认最大值是 这个目前区域左上角的那个数
					if(x1==x){ 
						maxX=x1;
						maxY=y1;
						break;
					}
					//一一比较选出目前区域最大的那个数
					else if(equation[x1][y1]>equation[maxX][maxY]){
						
						maxX=x1;
						maxY=y1;
					}
				}
			}
			//根据找到的横纵坐标,对当前区域矩阵开始换位
			//如果横坐标或者纵坐标是在目前区域的第一行/第一列,那么就不用调换相应行/列的位置
			if(maxX!=x){ //如果横坐标不是目前区域的第一行
				//上下方向调换位置
				for(int y2=x;y2<n+1;y2++){
					dbChange=equation[maxX][y2];
					equation[maxX][y2]=equation[x][y2];
					equation[x][y2]=dbChange;
				}
			}
			if(maxY!=x){ //如果纵坐标不是目前区域的第一列
				//左右方向调换位置
				for(int x2=x;x2<n;x2++){
					dbChange=equation[x2][maxY];
					equation[x2][maxY]=equation[x2][x];
					equation[x2][x]=dbChange;
				}
				//更改x1,x2,x3矩阵的位置,方便之后进行输出
				inChange=num[x];
				num[x]=num[maxY];
				num[maxY]=inChange;
			}
		}
		
		//求上三角矩阵
		for(int x=0;x<n-1;x++) {
			for(int y=x;y<n-1;y++) {
				//记录所求两行的倍数关系
				mul=-(equation[y+1][x]/equation[x][x]);
				for(int a=x;a<n+1;a++) {
					//更新矩阵数据
					equation[y+1][a]=equation[y+1][a]+equation[x][a]*mul;
				}
			}
		}
		
		System.out.println("主元素消去法计算结果为:");
		//解出结果
		for(int x=n-1;x>=0;x--) {
			//每次循环都让result等于常数项
			result=equation[x][n];
			for(int y=n;y>x;y--) {
				if(y-1==x) { //如果运行到了 未知数*系数 = 常数项 的时候
					result=result/equation[x][y-1];
				}
				else {  //如果运行到了  未知数*系数 + 已求解的未知数*系数 = 常数项 的时候
					result=result-(equation[x][y-1]*X[y-1]);
				}
			}
			X[x]=result; //记录求解出来的x值
			//为方便浏览,以及根据题中要求,选择保留5位小数
			BigDecimal b = new BigDecimal(result);
			result = b.setScale(5, BigDecimal.ROUND_HALF_UP).doubleValue(); 
			//去掉小数中的科学计数法形式:
			BigDecimal bg=new BigDecimal(result+""); 
			System.out.println("x"+(x+1)+"="+bg);
		}
	}
}

输入和输出结果:

在这里插入图片描述
如果您有幸看到本文章,请注意,本段代码仍有很多问题亟待解决。
①本段代码只适用于这道题,目前没有测试更多阶数的数据时,能否输出正确结果。
②本段代码只适用于解线性方程组!
③本段代码过于冗长难懂,我自己在写的时候就算想到加注释,也无法让我感到清晰易懂(我相信各位有经验的程序员更无法理解了)。所以如果您有更好的办法去实现,或者更好的建议来修改,我会仔细斟酌并努力学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

只爭朝夕不負韶華

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值