public class Matrix { public int row; // 행 전역변수 선언 public int col; // 열 전역변수 선언 public double[][] values; // 2차원 배열 행렬 전역변수 선언
public Matrix(int row, int col) { // 생성자 Matrix 생성 this.row = row; // 행의 값을 받는다. this.col = col; // 열의 값을 받는다. values = new double[row][col];// 전역변수 values에 row값과 col값을 넣어준다. }
class Invers // Invers 메소드 { determi det = new determi(); // 행렬식을 이용하기 위해 불러옴
public double[][] Invers(Matrix mat) { Matrix inv = new Matrix(mat.row, mat.col); // 역행렬을 저장한 행렬 생성 Matrix cofactor = new Matrix(mat.row, mat.col); double de = (double) 1 / det.data(mat);
if (det.data(mat) == 0) // 행렬식이 0일 경우 { System.out.println("역행렬이 있지 않습니다.");// 메세지 툴력 System.exit(0); // 그리고 시스템 exit }
for (int i = 0; i < mat.row; i++) { // 0부터 행 값까지 반복 for (int j = 0; j < mat.col; j++) {// 0부터 열 값까지 반복 cofactor.values[i][j] = Mino(mat, i, j); inv.values[j][i] = de * Math.pow(-1, i + j) * cofactor.values[i][j]; } } return inv.values;// inv를 리턴한다. } public double Mino(Matrix mat, int r, int c) {// 여인수전개를 위한 메소드 double cof; Matrix minor = new Matrix(mat.row - 1, mat.col - 1); int k = 0; if (k == r) { k++; } // C_ij의 소행렬은 i행j열을 제외하므로 이런 if를 쓴다. for (int i = 0; i < minor.row; i++) // 0부터 행값까지 반복 { int l = 0; // l은 초기값으로 0 if (l == c) { l++; }// l값이 열값과 같다면 l증가 if (k == r) { k++; }// k값이 행값과 같다면 k증가 for (int j = 0; j < minor.col; j++) { if (l == c) { l++; } // 열값과 같아면 l증가 minor.values[i][j] = mat.values[k][l]; l++; } k++; } cof = det.data(minor);// 소행렬을 구해 반환 return cof; } }
static class determi { static int order; static double[][] matrix;
public double data(Matrix mat) // 행렬식을 구할 행렬을 받는다. { matrix = new double[mat.row][mat.col]; order = mat.row; // order는 받은 행렬의 행의 수이다. for (int i = 0; i < mat.row; i++)// i를 행의수만큼 돌리고 { for (int j = 0; j < mat.col; j++) // j는 열의수만큼 돌려서 { matrix[i][j] = mat.values[i][j]; // matrix에 mat과 같은 값을 넣는다. } } return compute(); // 리턴을 compute함수로 시켜준다. }
public static double compute() // 그럼 여기로 오는데, { double check[] = new double[20]; // check란 20칸짜리 배열을 만든다. double det = 0; // det는 초기화하고 int row, col = 0; // row와 col도 초기화선언한다. for (row = 0; row < order; row++) // row는 받은 행의 수 만큼 돌리고 { check[row] = 1; // 이때 check의 행의수만큼의 index를 1로 지정 }
if (order == 1)// 만약 order가 1이면 { det = matrix[0][0]; // det는 a11값이 된다. }
for (row = 0; row < order; row++) // 다시 row를 수만큼 돌림 { check[row] = 0;// row[i]에 0을 집어넣음 det += matrix[row][0] * Math.pow(-1, row) * minor(row, col + 1, check); // det를 1열의 수 곱하기 minor함수에서 받은 값으로 온다 check[row] = 1; // 이렇게 계산 되면 다시 check를 1로 해준다. } return det; // det 값을 반환 }
public static double minor(int Row, int Col, double trans[]) { double result = 0;// 결과값으로 초기값을 0을 준다. int i = 0; if ((order - Col) == 0) { return 1; } for (int row = 0; row < order; row++)// 0부터 { if (trans[row] != 0)// 만약 trans[row]가 0이 아니라면 { trans[row] = 0; // 0을 넣어준다. result += matrix[row][Col] * Math.pow(-1, (double) i) * minor(row, Col + 1, trans); // 여인수전개에 의한 식이다. 재귀함수로 계속 돌리게된다. trans[row] = 1; // trans[row]에 1을 넣어준다. i++;// i 값 증가 } } return result; // result 반환 } }
}
|