1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

C言語で逆行列を求める

Last updated at Posted at 2022-07-24

Python なら numpy で簡単に求められる逆行列ですが、C ではそうもいきません。

そこで、先人たちの知恵を借りるべくいろいろとインターネットを漁ったのですが、自分にとってちょうどよいサンプルプログラムがなかったので、近しいサンプルを参考にして作り直してみました。

バグなどがあれば教えてください🙏

プログラム

inverse.c
#include <stdio.h>
#include <stdlib.h>

#define N 3

void inverse_matrix(long double **, int, long double **);
void get_minor(long double **, long double **, int, int, int);
long double calculate_determinant(long double **, int);

void inverse_matrix(long double **matrix, int order, long double **inv_matrix) {

  int i, j;
  long double inv_det;
  long double **minor;

  inv_det = 1.0 / calculate_determinant(matrix, order);
  
  minor = (long double **)calloc(order - 1, sizeof(long double *));
  for (i = 0; i < order - 1; i++)
    minor[i] = (long double *)calloc(order - 1, sizeof(long double));
  
  for (j = 0; j < order; j++) {
    for (i = 0; i < order; i++) {
      get_minor(matrix, minor, j, i, order);
      inv_matrix[i][j] = inv_det * calculate_determinant(minor, order - 1);
      if ( (i + j) % 2 == 1)
        inv_matrix[i][j] = -inv_matrix[i][j];
    }
  }
  
  for (i = 0; i < order - 1; i++)
    free(minor[i]);
  free(minor);
  
}


void get_minor(long double **src, long double **dest, int row, int col, int order) {
  
  int i, j;
  int col_count = 0;
  int row_count = 0;

  for (j = 0; j < order; j++) {
    if (j != row) {
      col_count = 0;
      for (i = 0; i < order; i++) {
        if (i != col) {
          dest[row_count][col_count] = src[j][i];
          col_count++;
        }
      }
      row_count++;
    }
  }

}


long double calculate_determinant(long double **matrix, int order) {

  int i;
  long double det = 0.0;
  long double **minor;
  
  if (order == 1)
    return matrix[0][0];
  
  minor = (long double **)calloc(order - 1, sizeof(long double *));
  for (i = 0; i < order - 1; i++)
    minor[i] = (long double *)calloc(order - 1, sizeof(long double));

  for (i = 0; i < order; i++) {
    get_minor(matrix, minor, 0, i, order);
    det += (i % 2 == 1 ? -1.0 : 1.0) * matrix[0][i] * calculate_determinant(minor, order - 1);
  }

  for (i = 0; i < order - 1; i++)
    free(minor[i]);
  free(minor);

  return det;
  
}


int main(void) {
  
  int i, j;
  long double **matrix, **inv_matrix;

  matrix = (long double **)calloc(N, sizeof(long double *));
  for (i = 0; i < N; i++)
    matrix[i] = (long double *)calloc(N, sizeof(long double));

  inv_matrix = (long double **)calloc(N, sizeof(long double *));
  for (i = 0; i < N; i++)
    inv_matrix[i] = (long double *)calloc(N, sizeof(long double));
  
  matrix[0][0] = 1;  matrix[0][1] = 1;  matrix[0][2] = 3;
  matrix[1][0] = 1;  matrix[1][1] = 3;  matrix[1][2] = -3;
  matrix[2][0] = -2; matrix[2][1] = -4; matrix[2][2] = -4;

  for (j = 0; j < N; j++) {
    for (i = 0; i < N; i++) {
      printf("%Lf, ", matrix[j][i]);
    }
    printf("\n");
  }

  /* 逆行列を求める */
  inverse_matrix(matrix, N, inv_matrix);
  
  for (j = 0; j < N; j++) {
    for (i = 0; i < N; i++) {
      printf("%Lf, ", inv_matrix[j][i]);
    }
    printf("\n");
  }

  for (i = 0; i < N; i++) {
    free(matrix[i]);
    free(inv_matrix[i]);
  }
  free(matrix);
  free(inv_matrix);
  
  return 0;
  
}

動作結果

1.000000, 1.000000, 3.000000,
1.000000, 3.000000, -3.000000,
-2.000000, -4.000000, -4.000000,

3.000000, 1.000000, 1.500000,
-1.250000, -0.250000, -0.750000,
-0.250000, -0.250000, -0.250000,
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?