0

我正在使用伴随方法计算矩阵的逆。首先我必须计算矩阵的行列式。为了计算行列式,我首先创建一个上三角矩阵,然后将对角线相乘以获得矩阵的行列式。下面给出了计算行列式的公式。

for(int cr = 1 ;cr < dd.length;cr++)
{ double factor = 0.0;      
  final   double[] firstrow = new double[dd.length] ; /* dd is a matrix*/

  for(int r = 0 ;r < dd.length; r++)  
 { firstrow[r] = dd[cr - 1][r]; }

for( int rowcount = cr + 0 ; rowcount< dd.length ; rowcount++)
{           
  factor = dd[rowcount][cr - 1] / firstrow[cr - 1];

for( int m = cr - 1 ; m < firstrow.length ; m++)
{  
dd[cr - 1][m] = firstrow[m] * factor;               /* multioly row by factor */                                                
dd[rowcount][m] = dd[rowcount][m] - dd[cr - 1][m];  /* our current row minus factored row */
dd[cr - 1][m] = firstrow[m];                        /* restore the original values to row */    
}    }} 

for(int d = 0 ; d < dd.length;d++)
{det *= dd[d][d];}    /* det is the determinant */

得到下三角矩阵后,对角线值的乘积成为矩阵的行列式。我已经尝试过这种方法并且它有效。但是,当我使用它来计算具有浮点值的 13 x 13 矩阵的行列式时,我得到的不是一个数值,它是 NaN 作为行列式。有人可以向我解释发生了什么。我有以下矩阵的示例值。

65.15078176822551
 731.664756199619
 1.5309584518179011E9
 1.7388182254012366E11
 3.3604905770182707E17
 1.77135880331128576E17

谢谢大家

4

2 回答 2

1

我怀疑问题与您使用factorto (我猜)减少数字的比例有关。我敢打赌firstrow[cr - 1],某些指数为零。随后除以零将创建 INF 或 NaN,并将传播到计算的其余部分。


顺便说一句,这个“公式”看起来不像计算行列式的标准方法,如下所述:

http://www.math.dartmouth.edu/archive/m8s00/public_html/handouts/matrices3/node7.html

标准版不涉及任何划分。你确定你的“公式”是正确的吗?

于 2012-09-10T02:28:31.967 回答
0

试试这个,你会得到任何维度矩阵的准确行列式。

这个类使用许多不同的方法使矩阵成为三角形,然后计算它的行​​列式。它可以用于高维矩阵,如 500 x 500 甚至更大。这门课的好处是你可以得到BigDecimal 的结果,所以没有无穷大,你总能得到准确的答案。顺便说一句,使用许多不同的方法并避免递归会导致更快的方法和更高的答案性能。希望它会有所帮助。

import java.math.BigDecimal;


public class DeterminantCalc {

private double[][] matrix;
private int sign = 1;


DeterminantCalc(double[][] matrix) {
    this.matrix = matrix;
}

public int getSign() {
    return sign;
}

public BigDecimal determinant() {

    BigDecimal deter;
    if (isUpperTriangular() || isLowerTriangular())
        deter = multiplyDiameter().multiply(BigDecimal.valueOf(sign));

    else {
        makeTriangular();
        deter = multiplyDiameter().multiply(BigDecimal.valueOf(sign));

    }
    return deter;
}


/*  receives a matrix and makes it triangular using allowed operations
    on columns and rows
*/
public void makeTriangular() {

    for (int j = 0; j < matrix.length; j++) {
        sortCol(j);
        for (int i = matrix.length - 1; i > j; i--) {
            if (matrix[i][j] == 0)
                continue;

            double x = matrix[i][j];
            double y = matrix[i - 1][j];
            multiplyRow(i, (-y / x));
            addRow(i, i - 1);
            multiplyRow(i, (-x / y));
        }
    }
}


public boolean isUpperTriangular() {

    if (matrix.length < 2)
        return false;

    for (int i = 0; i < matrix.length; i++) {
        for (int j = 0; j < i; j++) {
            if (matrix[i][j] != 0)
                return false;

        }

    }
    return true;
}


public boolean isLowerTriangular() {

    if (matrix.length < 2)
        return false;

    for (int j = 0; j < matrix.length; j++) {
        for (int i = 0; j > i; i++) {
            if (matrix[i][j] != 0)
                return false;

        }

    }
    return true;
}


public BigDecimal multiplyDiameter() {

    BigDecimal result = BigDecimal.ONE;
    for (int i = 0; i < matrix.length; i++) {
        for (int j = 0; j < matrix.length; j++) {
            if (i == j)
                result = result.multiply(BigDecimal.valueOf(matrix[i][j]));

        }

    }
    return result;
}


// when matrix[i][j] = 0 it makes it's value non-zero
public void makeNonZero(int rowPos, int colPos) {

    int len = matrix.length;

    outer:
    for (int i = 0; i < len; i++) {
        for (int j = 0; j < len; j++) {
            if (matrix[i][j] != 0) {
                if (i == rowPos) { // found "!= 0" in it's own row, so cols must be added
                    addCol(colPos, j);
                    break outer;

                }
                if (j == colPos) { // found "!= 0" in it's own col, so rows must be added
                    addRow(rowPos, i);
                    break outer;
                }
            }
        }
    }
}


//add row1 to row2 and store in row1
public void addRow(int row1, int row2) {

    for (int j = 0; j < matrix.length; j++)
        matrix[row1][j] += matrix[row2][j];
}


//add col1 to col2 and store in col1
public void addCol(int col1, int col2) {

    for (int i = 0; i < matrix.length; i++)
        matrix[i][col1] += matrix[i][col2];
}


//multiply the whole row by num
public void multiplyRow(int row, double num) {

    if (num < 0)
        sign *= -1;


    for (int j = 0; j < matrix.length; j++) {
        matrix[row][j] *= num;
    }
}


//multiply the whole column by num
public void multiplyCol(int col, double num) {

    if (num < 0)
        sign *= -1;

    for (int i = 0; i < matrix.length; i++)
        matrix[i][col] *= num;

}


// sort the cols from the biggest to the lowest value
public void sortCol(int col) {

    for (int i = matrix.length - 1; i >= col; i--) {
        for (int k = matrix.length - 1; k >= col; k--) {
            double tmp1 = matrix[i][col];
            double tmp2 = matrix[k][col];

            if (Math.abs(tmp1) < Math.abs(tmp2))
                replaceRow(i, k);
        }
    }
}


//replace row1 with row2
public void replaceRow(int row1, int row2) {

    if (row1 != row2)
        sign *= -1;

    double[] tempRow = new double[matrix.length];

    for (int j = 0; j < matrix.length; j++) {
        tempRow[j] = matrix[row1][j];
        matrix[row1][j] = matrix[row2][j];
        matrix[row2][j] = tempRow[j];
    }
}


//replace col1 with col2
public void replaceCol(int col1, int col2) {

    if (col1 != col2)
        sign *= -1;

    System.out.printf("replace col%d with col%d, sign = %d%n", col1, col2, sign);
    double[][] tempCol = new double[matrix.length][1];

    for (int i = 0; i < matrix.length; i++) {
        tempCol[i][0] = matrix[i][col1];
        matrix[i][col1] = matrix[i][col2];
        matrix[i][col2] = tempCol[i][0];
    }
}

}

然后这个类从用户那里接收一个 nxn 的矩阵,或者可以生成一个 nxn 的随机矩阵,然后计算它的行​​列式。它还显示了解决方案和最终的三角矩阵。

import java.math.BigDecimal;
import java.security.SecureRandom;
import java.text.NumberFormat;
import java.util.Scanner;


public class DeterminantTest {

public static void main(String[] args) {

    String determinant;

    //generating random numbers
int len = 500;
SecureRandom random = new SecureRandom();
double[][] matrix = new double[len][len];

for (int i = 0; i < len; i++) {
    for (int j = 0; j < len; j++) {
        matrix[i][j] = random.nextInt(500);
        System.out.printf("%15.2f", matrix[i][j]);
    }
}
System.out.println();

/*double[][] matrix = {
    {1, 5, 2, -2, 3, 2, 5, 1, 0, 5},
    {4, 6, 0, -2, -2, 0, 1, 1, -2, 1},
    {0, 5, 1, 0, 1, -5, -9, 0, 4, 1},
    {2, 3, 5, -1, 2, 2, 0, 4, 5, -1},
    {1, 0, 3, -1, 5, 1, 0, 2, 0, 2},
    {1, 1, 0, -2, 5, 1, 2, 1, 1, 6},
    {1, 0, 1, -1, 1, 1, 0, 1, 1, 1},
    {1, 5, 5, 0, 3, 5, 5, 0, 0, 6},
    {1, -5, 2, -2, 3, 2, 5, 1, 1, 5},
    {1, 5, -2, -2, 3, 1, 5, 0, 0, 1}
};

    double[][] matrix = menu();*/

    DeterminantCalc deter = new DeterminantCalc(matrix);

    BigDecimal det = deter.determinant();

    determinant = NumberFormat.getInstance().format(det);

    for (int i = 0; i < matrix.length; i++) {
        for (int j = 0; j < matrix.length; j++) {
            System.out.printf("%15.2f", matrix[i][j]);
        }
        System.out.println();
    }

    System.out.println();
    System.out.printf("%s%s%n", "Determinant: ", determinant);
    System.out.printf("%s%d", "sign: ", deter.getSign());

}


public static double[][] menu() {

    Scanner scanner = new Scanner(System.in);

    System.out.print("Matrix Dimension: ");
    int dim = scanner.nextInt();

    double[][] inputMatrix = new double[dim][dim];

    System.out.println("Set the Matrix: ");
    for (int i = 0; i < dim; i++) {
        System.out.printf("%5s%d%n", "row", i + 1);
        for (int j = 0; j < dim; j++) {

            System.out.printf("M[%d][%d] = ", i + 1, j + 1);
            inputMatrix[i][j] = scanner.nextDouble();
        }
        System.out.println();
    }
    scanner.close();

    return inputMatrix;
}

}

于 2019-05-21T06:05:35.587 回答