Java 中的矩阵运算
一组静态方法,在所有涉及矩阵的数学计算中都至关重要。
引言
本文介绍了Java中用于矩阵加法、乘法、逆、转置和其他相关运算的一些基本方法。 简要解释了矩阵运算,并提供了外部链接以获取更多详细信息。 主要函数以static
实用方法给出。 本文中的所有方法都经过单元测试,测试代码是附件的一部分。
正如一位成员(即César de Souza)所建议的那样,矩阵分解方法,例如Cholesky分解和LU分解在矩阵运算中更为常见。
Using the Code
矩阵是数字的二维数组。 我在Java中使用三个参数定义矩阵; 即,行数(nrows
),列数(ncols
)和数据作为double
数组。
public class Matrix {
private int nrows;
private int ncols;
private double[][] data;
public Matrix(double[][] dat) {
this.data = dat;
this.nrows = dat.length;
this.ncols = dat[0].length;
}
public Matrix(int nrow, int ncol) {
this.nrows = nrow;
this.ncols = ncol;
data = new double[nrow][ncol];
}
矩阵是数学的基础,其运算在定量学科中至关重要。 在单独的文章中,我将使用这些函数进行统计建模。
转置
矩阵的转置是通过交换行和列来产生的。
public static Matrix transpose(Matrix matrix) {
Matrix transposedMatrix = new Matrix(matrix.getNcols(), matrix.getNrows());
for (int i=0;i<matrix.getNrows();i++) {
for (int j=0;j<matrix.getNcols();j++) {
transposedMatrix.setValueAt(j, i, matrix.getValueAt(i, j));
}
}
return transposedMatrix;
}
有关矩阵转置的更多信息,请访问此链接。
方阵的行列式
方阵的行数和列数相等。 对于这些矩阵,可以使用以下方法来计算行列式。 我们将在本文后面使用此函数来查找矩阵的逆。
public static double determinant(Matrix matrix) throws NoSquareException {
if (!matrix.isSquare())
throw new NoSquareException("matrix need to be square.");
if (matrix.size() == 1) {
return matrix.getValueAt(0, 0);
}
if (matrix.size()==2) {
return (matrix.getValueAt(0, 0) * matrix.getValueAt(1, 1)) -
( matrix.getValueAt(0, 1) * matrix.getValueAt(1, 0));
}
double sum = 0.0;
for (int i=0; i<matrix.getNcols(); i++) {
sum += changeSign(i) * matrix.getValueAt(0, i) * determinant(createSubMatrix(matrix, 0, i));
}
return sum;
}
changeSign(i)
是一种方法,如果i是偶数则返回1
,否则返回-1
。 有关行列式的更多信息,请参见此处。
上面的方法是一个递归函数,它使用下面给出的createSubMatrix
方法将较大的矩阵分解为较小的矩阵
public static Matrix createSubMatrix(Matrix matrix, int excluding_row, int excluding_col) {
Matrix mat = new Matrix(matrix.getNrows()-1, matrix.getNcols()-1);
int r = -1;
for (int i=0;i<matrix.getNrows();i++) {
if (i==excluding_row)
continue;
r++;
int c = -1;
for (int j=0;j<matrix.getNcols();j++) {
if (j==excluding_col)
continue;
mat.setValueAt(r, ++c, matrix.getValueAt(i, j));
}
}
return mat;
}
此方法的输入参数是原始矩阵以及需要从原始矩阵中删除以创建子矩阵的行和列索引号。
矩阵的余子式
矩阵A的余子式是矩阵C,其中元素Cij的值等于通过从矩阵A中删除第i行和第j列创建的矩阵的行列式。 这是计算余子式矩阵的方法
public static Matrix cofactor(Matrix matrix) throws NoSquareException {
Matrix mat = new Matrix(matrix.getNrows(), matrix.getNcols());
for (int i=0;i<matrix.getNrows();i++) {
for (int j=0; j<matrix.getNcols();j++) {
mat.setValueAt(i, j, changeSign(i) * changeSign(j) *
determinant(createSubMatrix(matrix, i, j)));
}
}
return mat;
}
此方法对于计算下一节中给出的矩阵的逆是必需的。 有关余子式的详细信息,请访问此链接。
矩阵的逆
方阵A的逆是矩阵A-1,其中AA-1=I。 I是单位矩阵(有关更多详细信息,请参见此链接)。
public static Matrix inverse(Matrix matrix) throws NoSquareException {
return (transpose(cofactor(matrix)).multiplyByConstant(1.0/determinant(matrix)));
}
在此方法中,通过找到该矩阵的余子式的转置并除以该矩阵的行列式来计算矩阵的逆。 并非所有方阵都有逆。 如果矩阵不可逆(奇异矩阵),则从上述方法中获得的矩阵的值将为NAN(代表非数字)或无穷大。
对于矩阵乘法,加法和减法,请参见附加的代码。
关注点
以上所有运算都是线性代数的基础,也许矩阵的逆是其中最难理解和实现的运算。
历史
这是第一个版本(v1.0.2)。