⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linearequationgroup.java

📁 数值分析算法源码(java) 这个学期一边学习java一边学习数值分析,因此用java写了一个数值分析算法的软件包numericalAnalysis. [说明] 适合使用者:会java的
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
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 + -