其中D为对角阵,L为下三角矩阵,U为上三角矩阵。
之后确定迭代格式:X^(k+1) = D^(-1)(b-(L+U)x^(k)) ,这里^表示的是上标,括号内数字即迭代次数(k = 0,1,......)
再选取初始迭代向量X^(0),开始逐次迭代。
/**
* Jacobi迭代法
* @param a
* @param b
* @return
*/
public static double[] Jacobi(double[][] a, double[] b) {
int n = a.length;
double sum = 0;
double e = 0.001;
double z;
int i;
double[] x = new double[n];
double[] y = new double[n];
while (true) {
//按迭代式迭代
for (i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i != j) {
sum += a[i][j] * x[j];
}
}
y[i] = (b[i] - sum) / a[i][i];
sum = 0;
}
//达到精度后终止
i = 0;
while (i < n) {
z = Math.abs(x[i] - y[i]);
if (z > e)
break;
i++;
}
if (i != n) {
for (i = 0; i < n; i++)
x[i] = y[i];
}else if (i == n)
break;
}
return y;
}
/**
* 高斯-赛德尔方法
* @param a
* @param b
* @return
*/
public static double[] GaussSeidel(double[][] a,double[] b){
int n = a.length;
double sum = 0;
double e = 0.001;
double z;
int i;
double[] x = new double[n];
double[] y = new double[n];
while (true) {
//按迭代式迭代
for (i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
//跟Jacobi的不同之处
if (i < j) {
sum += a[i][j] * y[j];
}else if(i>j){
sum += a[i][j] * x[j];
}
}
y[i] = (b[i] - sum) / a[i][i];
sum = 0;
}
//达到精度后终止
i = 0;
while (i < n) {
z = Math.abs(x[i] - y[i]);
if (z > e)
break;
i++;
}
if (i != n) {
for (i = 0; i < n; i++)
x[i] = y[i];
}else if (i == n)
break;
}
return y;
}
/**
* 逐次超松弛方法SOR
* @param a
* @param b
* @return
*/
public static double[] SOR(double[][] a,double[] b,double m){
int n = a.length;
double sum = 0;
double e = 0.001;
double z;
int i;
double[] x = new double[n];
double[] y = new double[n];
while (true) {
//按迭代式迭代
for (i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
//跟Jacobi的不同之处
if (i < j) {
sum += a[i][j] * y[j];
}else if(i>j){
sum += a[i][j] * x[j];
}
}
y[i] = (1-m)*x[i]+(m*(b[i] - sum))/ a[i][i];
sum = 0;
}
//达到精度后终止
i = 0;
while (i < n) {
z = Math.abs(x[i] - y[i]);
if (z > e)
break;
i++;
}
if (i != n) {
for (i = 0; i < n; i++)
x[i] = y[i];
}else if (i == n)
break;
}
return y;
}
附上完整的实验代码:
package com.kexin.lab3;
/**
* 用迭代法求解线性方程组: Jacobi、Gauss-Seidel、SOR
*
* @author KeXin
*
*/
public class DieDai {
/**
* Jacobi迭代法
* @param a
* @param b
* @return
*/
public static double[] Jacobi(double[][] a, double[] b) {
int n = a.length;
double sum = 0;
double e = 0.001;
double z;
int i;
double[] x = new double[n];
double[] y = new double[n];
while (true) {
//按迭代式迭代
for (i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i != j) {
sum += a[i][j] * x[j];
}
}
y[i] = (b[i] - sum) / a[i][i];
sum = 0;
}
//达到精度后终止
i = 0;
while (i < n) {
z = Math.abs(x[i] - y[i]);
if (z > e)
break;
i++;
}
if (i != n) {
for (i = 0; i < n; i++)
x[i] = y[i];
}else if (i == n)
break;
}
return y;
}
/**
* 高斯-赛德尔方法
* @param a
* @param b
* @return
*/
public static double[] GaussSeidel(double[][] a,double[] b){
int n = a.length;
double sum = 0;
double e = 0.001;
double z;
int i;
double[] x = new double[n];
double[] y = new double[n];
while (true) {
//按迭代式迭代
for (i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
//跟Jacobi的不同之处
if (i < j) {
sum += a[i][j] * y[j];
}else if(i>j){
sum += a[i][j] * x[j];
}
}
y[i] = (b[i] - sum) / a[i][i];
sum = 0;
}
//达到精度后终止
i = 0;
while (i < n) {
z = Math.abs(x[i] - y[i]);
if (z > e)
break;
i++;
}
if (i != n) {
for (i = 0; i < n; i++)
x[i] = y[i];
}else if (i == n)
break;
}
return y;
}
/**
* 逐次超松弛方法SOR
* @param a
* @param b
* @return
*/
public static double[] SOR(double[][] a,double[] b,double m){
int n = a.length;
double sum = 0;
double e = 0.001;
double z;
int i;
double[] x = new double[n];
double[] y = new double[n];
while (true) {
//按迭代式迭代
for (i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
//跟Jacobi的不同之处
if (i < j) {
sum += a[i][j] * y[j];
}else if(i>j){
sum += a[i][j] * x[j];
}
}
y[i] = (1-m)*x[i]+(m*(b[i] - sum))/ a[i][i];
sum = 0;
}
//达到精度后终止
i = 0;
while (i < n) {
z = Math.abs(x[i] - y[i]);
if (z > e)
break;
i++;
}
if (i != n) {
for (i = 0; i < n; i++)
x[i] = y[i];
}else if (i == n)
break;
}
return y;
}
/**
* 打印数组
* @param result
*/
public static void PrintArray(String str,double[] result){
int n = result.length;
System.out.print(str + "\n[");
for(int i =0;i