高斯消元法java_如何基于java实现Gauss消元法过程解析

本文介绍了高斯消元法的原理和步骤,包括如何解决分母很小的问题。提供了一种使用Java实现列主元高斯消元法的代码示例,详细解释了消元法和回代法的过程。
摘要由CSDN通过智能技术生成

补充知识:

要理解Gauss消去法,首先来看一个例子:

d5d2a6fd66da454dc4ff60e6d521b4c7.png

从上例子可以看出,高斯消去法实际上就是我们初中学的阶二元一次方程组,只不过那里的未知数个数$n=2$

$n>2$时,Gauss消去法的思路实际上和解二元一次方程组是一样的,方法如下:

将n方程组中的n−1个方程通过消元,形成一个与原方程组等价的一个新方程组,新方程组中的n−1个方程仅包含n−1个未知数。

故问题就转化为了求解n−1元的方程组,这样我们可以继续消元,以次类推,直到最后一个方程组为一元一次方程组

从最后一个一元一次方程组求解出最后一个未知量,然后逐步回代入之前的方程组,从而得到所有的未知数。

我们可以看到Gauss实际上就分为两步:消去和回代

下面通过一般化得到Gauss消元法的求解过程

38690413462643897b457128ae135e4f.png

bde19a510bcf639b609a154fa2fea824.png

a89499737d2a630724a7dc86474bc6e0.png

以上就是Gauss消去法的基本步骤,我们再回过头看看有没有什么问题?

我们在求比例$l_{ik}= \frac{a_{ik}^{\left (k-1 \right )}}{a_{kk}^{\left (k-1 \right )}}$时,如果分母很小,即:

6962ed211648aa62619b3366c9dfb68d.png

$l_{ik}\rightarrow \infty$,那么

3cbb856bf4100aa002b123f3600c6291.png

总结一下,能否使用Gauss消元法的情况

bfa9ce390af4f345c16ec8f39ff5fe1e.png

为了解决这个问题,我们可以使用列主元Gauss消元法。

16f43b9ecd7c51e92c8641517d288030.png

参考了一些网上的代码,这里给出Gauss的Java实现

package peterxiazhe;

import java.util.Scanner;

public class Gauss {

/**

* 列主元高斯消去法

*/

static double A[][];

static double b[];

static double x[];

static int n; //n表示未知数的个数

static int n_2; //记录换行的次数

public static void main(String[] args) {

System.out.println("--------------输入方程组未知数的个数---------------");

Scanner sc = new Scanner(System.in);

n = sc.nextInt();

A = new double[n][n];

b = new double[n];

x = new double[n];

System.out.println("--------------输入方程组的系数矩阵A:---------------");

for(int i = 0; i < n; i++) {

for(int j = 0; j < n; j++) {

A[i][j] = sc.nextDouble();

}

}

System.out.println("--------------输入方程组的常量向量b:---------------");

for(int i = 0; i < n; i++) {

b[i] = sc.nextDouble();

}

Elimination();

BackSubstitution();

PrintRoot();

}

//消元法

public static void Elimination() {

PrintA();

for(int k = 0; k < n; k++) {

WrapRow(k);

for(int i = k+1; i < n; i++) {

double l = A[i][k] / A[k][k];

A[i][k] = 0;

for(int j = k+1; j < n; j++) {

A[i][j] = A[i][j] - l * A[k][j];

}

b[i] = b[i] - l * b[k];

}

//System.out.println("第" + k + "次消元后:");

//PrintA();

}

}

//回代法

public static void BackSubstitution() {

x[n-1] = b[n-1] / A[n-1][n-1];

for(int i = n - 2; i >= 0; i--) {

x[i] = (b[i] - solve(i)) / A[i][i];

}

}

public static double solve(int i) {

double result = 0.0;

for(int j = i; j < n; j++)

result += A[i][j] * x[j];

return result;

}

//输出方程组的根

public static void PrintRoot() {

System.out.println("--------------方程组的根为---------------");

for(int i = 0; i < n; i++) {

System.out.println("x" + (i+1) + " = " + x[i]);

}

}

//交换Swap函数???

public static void Swap(double[] ar, int x, int y) {

Double tmp = ar[x];

ar[x] = ar[y];

ar[y] = tmp;

}

public static void PrintA() { //输出A的增广矩阵

//System.out.println("--------------增广矩阵---------------");

for(int i = 0; i < n; i++) {

for(int j = 0; j < n; j++) {

System.out.print(A[i][j] + " ");

}

System.out.println(b[i]);

}

}

//交换矩阵的行

public static void WrapRow(int k) { //k表示第k+1轮消元

double maxElement = Math.abs(A[k][k]);

int WrapRowIndex = k; // 记住要交换的行

for(int i = k + 1; i < n; i++) {

if (Math.abs(A[i][k]) > maxElement) {

WrapRowIndex = i;

maxElement = A[i][k];

}

}

if (WrapRowIndex != k) { //交换求得最大主元

n_2 += 1;

System.out.println("k = " + k + "时," + "要交换的行为" + k + "和"+ WrapRowIndex);

//先交换A

for(int j = k; j < n; j++) {

double[] arr = {A[k][j], A[WrapRowIndex][j]};

Swap(arr, 0, 1);

A[k][j] = arr[0]; A[WrapRowIndex][j] = arr[1];

// double tmp = A[k][j];

// A[k][j] = A[WrapRowIndex][j];

// A[WrapRowIndex][j] = tmp;

}

//再交换b

double[] arr = {b[k], b[WrapRowIndex]};

Swap(arr, 0, 1);

b[k] = arr[0]; b[WrapRowIndex] = arr[1];

// double tmp = b[k];

// b[k] = b[WrapRowIndex];

// b[WrapRowIndex] = tmp;

System.out.println("--------------交换后---------------");

PrintA();

}

}

}

注意:由于Java不支持对基本数据类型的引用传递,这里使用了一个小技巧

java中交换两个基本数据类型的变量函数swap(int[] source,int i,int j)

java中函数的参数传递机制是:基本数据类型采用值传递,对象采用传引用。因此,如果要写一个交换两个int型变量数值的函数,还真是有点不方便,必须采用一个数组对象来作为辅助,具体实现如下:

//交换两个整数

private static void swap(int[] source, int i, int j) {

int temp = source[i];

source[i] = source[j];

source[j] = temp;

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值