本人是个新手,写下博客用于自我复习、自我总结。
如有错误之处,请各位大佬指出。
题目:
分别用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);
}
}
}
输入和输出结果:
如果您有幸看到本文章,请注意,本段代码仍有很多问题亟待解决。
①本段代码只适用于这道题,目前没有测试更多阶数的数据时,能否输出正确结果。
②本段代码只适用于解线性方程组!
③本段代码过于冗长难懂,我自己在写的时候就算想到加注释,也无法让我感到清晰易懂(我相信各位有经验的程序员更无法理解了)。所以如果您有更好的办法去实现,或者更好的建议来修改,我会仔细斟酌并努力学习。