最近学习了precalculus中的Cramers规则,并决定用Java编写一个算法来帮助我更好地理解它。
下面的代码可以100%正确地工作,但是它没有使用任何类型的for循环来以更简单的方式完成它所做的事情。
问:Java中是否有更优雅的Cramers规则实现?
我在想做一个基本的行列式方法,然后在需要取dx,dy和dz的行列式时做一些列交换。(对于Dx,将第4列与原始矩阵的第1列交换,然后取行列式并除以原始行列式。)
听起来不错吧?
public static void main(String[] args) {
int[][] matrix = new int[3][3];
matrix[0] = new int[] { 3, 5, -1, -2 };
matrix[1] = new int[] { 1, -4, 2, 13 };
matrix[2] = new int[] { 2, 4, 3, 1 };
int[] r = crame(matrix);
info("x: " + r[0] + ", y: " + r[1] + ", z: " + r[2]);
for(int i = 0; i < matrix.length; i++) {
int[] base = matrix[i];
if(check(base, r, base[3])) {
info("System " + (i+1) + " checks!");
} else {
info("System " + (i+1) + " fails check!");
}
}
}
public static int[] crame(int[][] m) {
int[] result;
if (m.length == 2) {
result = new int[2];
int D = (m[0][0] * m[1][1]) - (m[1][0] * m[0][1]);
int Dx = (m[0][2] * m[1][1]) - (m[1][2] * m[0][1]);
int Dy = (m[0][0] * m[1][2]) - (m[1][0] * m[0][2]);
result[0] = (int) (Dx / D);
result[1] = (int) (Dy / D);
} else if (m.length == 3) {
result = new int[3];
int D = (((m[0][2] * m[1][1] * m[0][2]) + (m[2][1] * m[1][2] * m[0][0]) + (m[2][2]
* m[1][0] * m[0][2])) - ((m[0][0] * m[1][1] * m[2][2])
+ (m[0][1] * m[1][2] * m[0][2]) + (m[0][2] * m[1][0] * m[2][1])));
int Dx = (((m[2][3] * m[1][1] * m[0][2]) + (m[2][1] * m[1][2] * m[0][3]) + (m[2][2]
* m[1][3] * m[0][1])) - ((m[0][3] * m[1][1] * m[2][2])
+ (m[0][1] * m[1][2] * m[2][3]) + (m[0][2] * m[1][3] * m[2][1])));
int Dy = (((m[2][0] * m[1][3] * m[0][2]) + (m[2][3] * m[1][2] * m[0][3]) + (m[2][2]
* m[1][0] * m[0][3])) - ((m[0][0] * m[1][3] * m[2][2])
+ (m[0][3] * m[1][2] * m[2][0]) + (m[0][2] * m[1][0] * m[2][3])));
int Dz = (((m[2][0] * m[1][1] * m[0][3]) + (m[2][1] * m[1][3] * m[0][0]) + (m[2][3]
* m[1][0] * m[0][1])) - ((m[0][0] * m[1][1] * m[2][3])
+ (m[0][1] * m[1][3] * m[2][0]) + (m[0][3] * m[1][0] * m[2][1])));
result[0] = (int) (Dx / D);
result[1] = (int) (Dy / D);
result[2] = (int) (Dz / D);
} else {
return new int[] {};
}
return result;
}
public static int product(int[] a, int[] b) {
int p = 0;
int[] fin = new int[(a.length -1)];
for(int x = 0; x < fin.length; x++) {
fin[x] = a[x] * b[x];
}
for (int f : fin) {
p += f;
}
return p;
}
public static boolean check(int[] a, int[] b, int z) {
return product(a, b) == z;
}
public static void info(String log) {
System.out.println(log);
}
我的问题是关于特定的算法,可以用来解决方程组只使用克莱默斯规则,有没有更优雅的算法?这个函数只为平方矩阵设计。
这不是一个家庭作业,在HS之后,我将学习CS,我一直致力于开发算法作为初步实践。
谢谢你检查这个
最佳答案
首先,Cramers法则是完美的:它给出了线性系统的代数解作为其系数的有理函数。
然而,实际上,它有其局限性。虽然对于2x2系统来说是最完美的公式,对于3x3系统来说仍然是很好的公式,但是如果以简单的方式实现,它的性能会随着每个额外的维度而恶化。
利用leverierfaddeev算法可以实现Cramers规则的几乎字面实现它只需要计算矩阵积和矩阵迹,以及矩阵对角线的处理它不仅计算矩阵A的行列式(以及特征多项式的其他系数),而且在其迭代矩阵中还具有a或协因子矩阵A关于这个矩阵有趣的事实是它允许把A*x=b的解写成(A#*b)/det(A),也就是说,A#*b的项已经是Cramers规则所要求的其他行列式。
Leverrier Faddeev需要N4+O(N3)操作。更复杂的萨缪尔森-b算法,得到了同样的结果,其复杂度为三分之一,即N4/3+O(N3)。
如果系统(A | b)首先转换成三角形,Cramers规则中所需行列式的计算就变得非常简单这可以通过gau_消去、aka lu分解(带数值稳定性旋转)或qr分解(最容易调试的应该是givens旋转的变量)来实现。在三角系统中,cramers规则的有效应用是向后替换。