问题描述
我有一个程序可以在 NxN 分数矩阵上运行逆矩阵计算。我选择这样做的算法是高斯消除算法。但是在对矩阵求逆后,结果值与预期值不同。
用于输入的矩阵:
[1/1,-43/252,-61/504,-3/8]
[0/1,1/1,-2/3,0/1]
[-5/81,-187/243,0/1]
[-1/1,0/1,1/1]
预期的矩阵输出:
[42/25,91/100,81/100,63/100]
[252/1775,7563/3550,5103/3550,189/3550]
[378/1775,12039/7100,15309/7100,567/7100]
[42/25,163/100]
实际矩阵输出:
[42/25,-160423/8076,-186456755/182802,-186639557/121868,163/100]
如您所见,只有 3 个矩阵单元格的值不正确。我针对其他几个矩阵对其进行了测试,我可以获得一些正确的输出,但并非总是如此。我真的不知道是什么原因造成的。
这里是程序的实际源代码:
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Matrix m = new Matrix(new Rational[][]{
{new Rational(1),new Rational(-43,252),new Rational(-61,504),new Rational(-3,8)},{new Rational(0),new Rational(1),new Rational(-2,3),new Rational(0)},{new Rational(-5,81),new Rational(-187,243),{new Rational(-1),new Rational(0),new Rational(1)},});
System.out.println(m.invert());;
}
}
class Rational {
int numerator;
int denominator;
Rational(int num) {
this.numerator = num;
this.denominator = 1;
}
Rational(int numerator,int denominator) {
if (numerator < 0 && denominator < 0)
this.numerator = Math.abs(numerator);
else
this.numerator = denominator < 0 ? -numerator : numerator;
this.denominator = Math.abs(denominator);
}
public Rational abs() { return new Rational(Math.abs(this.numerator),Math.abs(this.denominator)); }
public boolean greaterThan(Rational rhs) {
if (this.numerator * rhs.denominator > rhs.numerator * this.denominator) return true;
return false;
}
public Rational subtract(Rational rhs) {
return simplify(this.numerator * rhs.denominator - rhs.numerator * this.denominator,this.denominator * rhs.denominator);
}
public Rational multiply(Rational rhs) {
return simplify(this.numerator * rhs.numerator,this.denominator * rhs.denominator);
}
public Rational divide(Rational rhs) {
return simplify(this.numerator * rhs.denominator,this.denominator * rhs.numerator);
}
private Rational simplify(int num,int denom) {
int gcd = gcd(Math.abs(num),Math.abs(denom));
return gcd <= 0 ? new Rational(0) : new Rational(num / gcd,num == 0 ? 1 : denom / gcd);
}
public static int gcd(int i,int j) {
return j == 0 ? i : gcd(j,i % j);
}
@Override
public String toString() {
return numerator + "/" + denominator;
}
}
class Matrix {
Rational[][] rows;
Matrix(Rational[][] matrix) {
this.rows = matrix;
}
public Matrix(int dimensions) {
this.rows = new Rational[dimensions][dimensions];
Arrays.stream(rows).forEach(rationals -> Arrays.fill(rationals,new Rational(0)));
}
public Matrix invert() {
int n = rows.length;
Matrix x = new Matrix(n);
Matrix b = new Matrix(n).identity();
int index[] = new int[n];
// Transform the matrix into an upper triangle
System.out.println(this);
gaussian(index);
System.out.println(this);
// Update the matrix b[i][j] with the ratios stored
for (int i = 0; i < n - 1; ++i)
for (int j = i + 1; j < n; ++j)
for (int k = 0; k < n; ++k)
b.rows[index[j]][k] = b.rows[index[j]][k].subtract(rows[index[j]][i].multiply(b.rows[index[i]][k]));
// Perform backward substitutions
for (int i = 0; i < n; ++i) {
x.rows[n - 1][i] = b.rows[index[n - 1]][i].divide(rows[index[n - 1]][n - 1]);
for (int j = n - 2; j >= 0; --j) {
x.rows[j][i] = b.rows[index[j]][i];
for (int k = j + 1; k < n; ++k)
x.rows[j][i] = x.rows[j][i].subtract(rows[index[j]][k].multiply(x.rows[k][i]));
x.rows[j][i] = x.rows[j][i].divide(rows[index[j]][j]);
}
}
return x;
}
// Method to carry out the partial-pivoting Gaussian
// elimination. Here index[] stores pivoting order.
public void gaussian(int index[]) {
int n = index.length;
Rational c[] = new Rational[n];
// Initialize the index
for (int i = 0; i < n; ++i) index[i] = i;
// Find the rescaling factors,one from each row
for (int i = 0; i < n; ++i) {
Rational c1 = new Rational(0);
for (int j = 0; j < n; ++j) {
Rational c0 = rows[i][j].abs();
if (c0.greaterThan(c1)) c1 = c0;
}
c[i] = c1;
}
// Search the pivoting element from each column
int k = 0;
for (int j = 0; j < n - 1; ++j) {
Rational pi1 = new Rational(0);
for (int i = j; i < n; ++i) {
Rational pi0 = rows[index[i]][j].abs();
pi0 = pi0.divide(c[index[i]]);
if (pi0.greaterThan(pi1)) {
pi1 = pi0;
k = i;
}
}
// Interchange rows according to the pivoting order
int itmp = index[j];
index[j] = index[k];
index[k] = itmp;
for (int i = j + 1; i < n; ++i) {
Rational pj = rows[index[i]][j].divide(rows[index[j]][j]);
// Record pivoting ratios below the diagonal
rows[index[i]][j] = pj;
// Modify other elements accordingly
for (int l = j + 1; l<n; ++l)
rows[index[i]][l] = rows[index[i]][l].subtract(pj.multiply(rows[index[j]][l]));
}
}
}
public Matrix identity() {
for (int i = 0; i < rows.length; ++i)
for (int j = 0; j < rows[0].length; ++j)rows[i][j] = new Rational(j == i ? 1 : 0);
return new Matrix(rows);
}
@Override
public String toString() {
String s = "";
for (Rational[] row: rows) s += "\t" + Arrays.toString(row) + "\n";
return String.format("[\n%s]",s);
}
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)