📄 linearequationgroup.java
字号:
package numericalAnalysis.linearEquationGroup;
import java.text.DecimalFormat;
import numericalAnalysis.norm.Norm;
/**
* 本类定义了一个线性方程组,包括多种解法.注意:判断迭代法使用是否收敛未完成.对照书:数值分析第二版,史万明等编,北京理工大学出版社
* 也可以是过定方程组(系数矩阵和右边值照常输入),则只能用本类的overdetermined方法求解.
*
* @author 山
*
*/
public class LinearEquationGroup {
private int n;
private double[][] a;
private double[] b;
private DecimalFormat fmt = new DecimalFormat("0.######");
/**
* 构造一个新的线性方程组.
*
* @param n
* 未知数个数
* @param a
* n*n的系数矩阵,注意:必须定义a[i][j]为aij,即下标有0的元素不使用
* @param b
* 方程组右边的n*1的列向量,注意:必须定义b[i]为bi,即b[0]不使用
*/
public LinearEquationGroup(int n, double a[][], double b[]) {
this.n = n;
this.a = new double[a.length][a[1].length];
this.b = new double[b.length];
for (int i = 1; i < a.length; i++)
for (int j = 1; j < a[1].length; j++)
this.a[i][j] = a[i][j];
for (int i = 1; i < b.length; i++)
this.b[i] = b[i];
}
/**
* 打印出方程组用以确认无误.
*
* @return 方程组
*/
public String print() {
String output = "\n";
for (int i = 1; i < a.length; i++)
for (int j = 1; j < a[1].length+1; j++)
if (j == 1)
output += "(" + fmt.format(a[i][j]) + "x1)";
else if (j == n + 1)// 等式右边的常数也一起输出
output += "=(" + fmt.format(b[i]) + ")\n";
else
output += "+(" + fmt.format(a[i][j]) + "x" + j + ")";
return output;
}
/**
* 获取方程组的解(用高斯消元法解)
*
* @return 返回一个数组,注意:解xi就是数组的索引为i的元素(即下标0不使用)
*/
public double[] getSolution() {
double[][] u = new double[n + 1][n + 1], l = new double[n + 1][n + 1];
double[] z = new double[n + 1], x = new double[n + 1];
// compute lij uij zi
for (int i = 1; i < n + 1; i++)
l[i][i] = 1;
for (int i = 1; i < n + 1; i++)
for (int j = 1; j < n + 1; j++)
if (i > j) {
double sum = 0;
for (int k = 1; k < j; k++)
sum += l[i][k] * u[k][j];
l[i][j] = (a[i][j] - sum) / u[j][j];
} else {
double sum = 0;
for (int k = 1; k < i; k++)
sum += l[i][k] * u[k][j];
u[i][j] = a[i][j] - sum;
}
for (int i = 1; i < n + 1; i++) {
double sum = 0;
for (int k = 1; k < i; k++)
sum += l[i][k] * z[k];
z[i] = b[i] - sum;
}
// compute xi
for (int i = n; i > 0; i--) {
double sum = 0;
for (int k = i + 1; k < n + 1; k++)
sum += u[i][k] * x[k];
x[i] = (z[i] - sum) / u[i][i];
}
return x;
}
/**
* 高斯消元法解.
*
* @return 结果
*/
public String gaussElimination() {
double[][] u = new double[n + 1][n + 1], l = new double[n + 1][n + 1];
double[] z = new double[n + 1], x = new double[n + 1];
String output = "\n";
// compute lij uij zi
for (int i = 1; i < n + 1; i++)
l[i][i] = 1;
for (int i = 1; i < n + 1; i++)
for (int j = 1; j < n + 1; j++)
if (i > j) {
double sum = 0;
for (int k = 1; k < j; k++)
sum += l[i][k] * u[k][j];
l[i][j] = (a[i][j] - sum) / u[j][j];
} else {
double sum = 0;
for (int k = 1; k < i; k++)
sum += l[i][k] * u[k][j];
u[i][j] = a[i][j] - sum;
}
for (int i = 1; i < n + 1; i++) {
double sum = 0;
for (int k = 1; k < i; k++)
sum += l[i][k] * z[k];
z[i] = b[i] - sum;
}
// compute xi
for (int i = n; i > 0; i--) {
double sum = 0;
for (int k = i + 1; k < n + 1; k++)
sum += u[i][k] * x[k];
x[i] = (z[i] - sum) / u[i][i];
}
// output lij uij zi
output += "\n\n表格:\n";
for (int i = 1; i < n + 1; i++)
for (int j = 1; j < n + 2; j++)
if (j == n + 1)
output += "z" + i + "=(" + fmt.format(z[i]) + ")\n";
else if (i > j)
output += "l" + i + j + "=(" + fmt.format(l[i][j]) + ") ";
else
output += "u" + i + j + "=(" + fmt.format(u[i][j]) + ") ";
// output xi
output += "\n\n解:\n";
for (int i = n; i > 0; i--)
output += "x" + i + "=(" + fmt.format(x[i]) + ")\n";
return output;
}
/**
* 克劳特消元法解.
*
* @return 结果
*/
public String croutElimination() {
double[][] u = new double[n + 1][n + 1], l = new double[n + 1][n + 1];
double[] z = new double[n + 1], x = new double[n + 1];
String output = "\n";
// compute lij uij zi
for (int i = 1; i < n + 1; i++)
u[i][i] = 1;
for (int i = 1; i < n + 1; i++)
for (int j = 1; j < n + 1; j++)
if (i < j) {
double sum = 0;
for (int k = 1; k < i; k++)
sum += l[i][k] * u[k][j];
u[i][j] = (a[i][j] - sum) / l[i][i];
} else {
double sum = 0;
for (int k = 1; k < j; k++)
sum += l[i][k] * u[k][j];
l[i][j] = a[i][j] - sum;
}
for (int i = 1; i < n + 1; i++) {
double sum = 0;
for (int k = 1; k < i; k++)
sum += l[i][k] * z[k];
z[i] = (b[i] - sum) / l[i][i];
}
// compute xi
for (int i = n; i > 0; i--) {
double sum = 0;
for (int k = i + 1; k < n + 1; k++)
sum += u[i][k] * x[k];
x[i] = z[i] - sum;
}
// output lij uij zi
output += "\n\n表格:\n";
for (int i = 1; i < n + 1; i++)
for (int j = 1; j < n + 2; j++)
if (j == n + 1)
output += "z" + i + "=(" + fmt.format(z[i]) + ")\n";
else if (i > j)
output += "l" + i + j + "=(" + fmt.format(l[i][j]) + ") ";
else
output += "u" + i + j + "=(" + fmt.format(u[i][j]) + ") ";
// output xi
output += "\n\n解:\n";
for (int i = n; i > 0; i--)
output += "x" + i + "=(" + fmt.format(x[i]) + ")\n";
return output;
}
/**
* 平方根消元法.注意:方程组为对称的才能用本方法解,否则返回错误信息.
*
* @return 结果
*/
public String cholesky() {
double[][] u = new double[n + 1][n + 1], l = new double[n + 1][n + 1];
double[] z = new double[n + 1], x = new double[n + 1];
String output = "\n";
// whether the equation group is a symmetry equation group
boolean symmetry = true;
for (int i = 1; i < n + 1; i++)
for (int j = 1; j < n + 1; j++)
if (a[i][j] != a[j][i])
symmetry = false;
// begin to compute and output
if (symmetry == true) {
// compute lij uij zi
for (int j = 1; j < n + 1; j++)
for (int i = 1; i < n + 1; i++)
if (i > j) {
double sum = 0;
for (int k = 1; k < j; k++)
sum += l[i][k] * u[k][j];
l[i][j] = (a[i][j] - sum) / l[j][j];
} else if (i == j) {
double sum = 0;
for (int k = 1; k < i; k++)
sum += Math.pow(l[i][k], 2);
u[i][j] = l[i][j] = Math.sqrt(a[i][j] - sum);
} else
u[i][j] = l[j][i];
for (int i = 1; i < n + 1; i++) {
double sum = 0;
for (int k = 1; k < i; k++)
sum += l[i][k] * z[k];
z[i] = (b[i] - sum) / l[i][i];
}
// compute xi
for (int i = n; i > 0; i--) {
double sum = 0;
for (int k = i + 1; k < n + 1; k++)
sum += u[i][k] * x[k];
x[i] = (z[i] - sum) / u[i][i];
}
// output lij uij zi
output += "\n\n表格:\n";
for (int i = 1; i < n + 1; i++)
for (int j = 1; j < n + 2; j++)
if (j == n + 1)
output += "z" + i + "=(" + fmt.format(z[i]) + ")\n";
else if (i > j)
output += "l" + i + j + "=(" + fmt.format(l[i][j])
+ ") ";
else
output += "u" + i + j + "=(" + fmt.format(u[i][j])
+ ") ";
// output xi
output += "\n\n解:\n";
for (int i = n; i > 0; i--)
output += "x" + i + "=(" + fmt.format(x[i]) + ")\n";
} else
output += "注意!本方程组不是对称的,不能用本方法\n";
return output;
}
/**
* 追赶法
*
* @return 结果
*/
public String chase() {
double[][] l, u;
double[] cA, cB, c, d, z, x;
String output = "\n";
l = new double[n + 1][n + 1];
u = new double[n + 1][n + 1];
cA = new double[n + 1];
cB = new double[n + 1];
c = new double[n + 1];
d = new double[n + 1];
z = new double[n + 1];
x = new double[n + 1];
for (int i = 1; i < n + 1; i++) {
if (i == 1) {
cB[1] = a[1][1];
c[1] = a[1][2];
} else if (i == n) {
cA[n] = a[n][n - 1];
cB[n] = a[n][n];
} else {
cA[i] = a[i][i - 1];
cB[i] = a[i][i];
c[i] = a[i][i + 1];
}
}
for (int i = 1; i < n + 1; i++)
d[i] = b[i];
// compute li(i-1),lii,ui(i+1),zi
cA[1] = u[0][1] = z[0] = cA[1] = 0;
for (int i = 1; i < n + 1; i++) {
if (i != 1)
l[i][i - 1] = cA[i];
l[i][i] = cB[i] - cA[i] * u[i - 1][i];
if (i != n)
u[i][i + 1] = c[i] / l[i][i];
z[i] = (d[i] - cA[i] * z[i - 1]) / l[i][i];
}
// compute xi
x[n] = z[n];
for (int i = n - 1; i > 0; i--)
x[i] = z[i] - u[i][i + 1] * x[i + 1];
// output the chart
output += "\n表格:\n";
for (int i = 1; i < n + 1; i++)
if (i == 1)
output += "l" + i + i + "=" + l[i][i] + " " + "u" + i
+ (i + 1) + "=" + u[i][i + 1] + "\n";
else if (i == n)
output += "l" + i + (i - 1) + "=" + l[i][i - 1] + " " + "l"
+ i + i + "=" + l[i][i] + "\n";
else
output += "l" + i + (i - 1) + "=" + l[i][i - 1] + " " + "l"
+ i + i + "=" + l[i][i] + " " + "u" + i + (i + 1)
+ "=" + u[i][i + 1] + "\n";
// output the equations and result
output += "\n\n和zi,di有关的方程组及解:\n";
for (int i = 1; i < n + 1; i++)
if (i == 1)
output += "(" + l[i][i] + "z1)=" + "(" + d[i] + ")\n";
else
output += "(" + cA[i] + "z" + (i - 1) + ")+(" + l[i][i] + "z"
+ i + ")=(" + d[i] + ")\n";
output += "\n";
for (int i = 1; i < n + 1; i++)
output += "z" + i + "=" + z[i] + " ";
output += "\n\n和xi,zi有关的方程组及解:\n";
for (int i = 1; i < n + 1; i++)
if (i == n)
output += "(x" + n + ")=(" + z[i] + ")\n";
else
output += "(x" + i + ")+(" + u[i][i + 1] + "x" + (i + 1)
+ ")=(" + z[i] + ")\n";
output += "\n";
for (int i = n; i > 0; i--)
output += "x" + i + "=" + x[i] + " ";
return output;
}
/**
* 雅可比迭代法(收敛判断未完成).
*
* @param errAllowed
* 允许误差
* @param xIni
* 初值.注意:必须定义xIni[i]为xi.即xIni[0]不使用
* @return 结果
*/
public String jacobiIterative(double errAllowed, double[] xIni) {
double[][] g = new double[n + 1][n + 1];
double[] f = new double[n + 1], x = new double[n + 1], xLast = new double[n + 1];
String output = "\n";
boolean convergent = true;
// judge whether using this method is convergent(not right but useful)
for (int i = 1; i < n + 1; i++)
for (int j = 1; j < n + 1; j++)
if (a[i][j] == 0)
convergent = false;
for (int i = 1; i < n + 1; i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -