C 言語で行列の行列式を計算する

CCBeginner
オンラインで実践に進む

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、C 言語で正方行列の行列式を計算する方法を学びます。この実験では以下の手順がカバーされます。行列の次元と要素を読み取ること、再帰的手法または LU 分解法を使用して行列式を計算すること、そして最終結果を出力することです。ステップバイステップの指示に従って、最大 10x10 の正方行列を扱うことができるプログラムを作成するプロセスを進めます。これにより、行列の要素を動的に入力し、計算された行列式を表示することができます。

次元と要素の読み取り(正方行列)

このステップでは、C 言語で正方行列の次元と要素を読み取る方法を学びます。ユーザーが行列のサイズとその要素を動的に入力できるプログラムを作成します。

まず、行列の行列式を計算するための新しい C ファイルを作成しましょう。

cd ~/project
nano matrix_determinant.c

次に、行列の次元と要素を読み取るための以下のコードを追加します。

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

#define MAX_SIZE 10

int main() {
    int n, i, j;
    int matrix[MAX_SIZE][MAX_SIZE];

    // 行列の次元を読み取る
    printf("Enter the size of the square matrix (1-%d): ", MAX_SIZE);
    scanf("%d", &n);

    // 行列のサイズを検証する
    if (n < 1 || n > MAX_SIZE) {
        printf("Invalid matrix size. Please enter a size between 1 and %d.\n", MAX_SIZE);
        return 1;
    }

    // 行列の要素を読み取る
    printf("Enter the matrix elements:\n");
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            printf("Enter element [%d][%d]: ", i, j);
            scanf("%d", &matrix[i][j]);
        }
    }

    // 入力を検証するために行列を出力する
    printf("\nEntered Matrix:\n");
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }

    return 0;
}

プログラムをコンパイルして実行します。

gcc matrix_determinant.c -o matrix_determinant
./matrix_determinant

出力例:

Enter the size of the square matrix (1-10): 3
Enter the matrix elements:
Enter element [0][0]: 1
Enter element [0][1]: 2
Enter element [0][2]: 3
Enter element [1][0]: 4
Enter element [1][1]: 5
Enter element [1][2]: 6
Enter element [2][0]: 7
Enter element [2][1]: 8
Enter element [2][2]: 9

Entered Matrix:
1 2 3
4 5 6
7 8 9

コードを分解してみましょう。

  • 過度のメモリ割り当てを防ぐために、最大行列サイズを 10 に定義しています。
  • プログラムは最初にユーザーに行列のサイズを入力するように求めます。
  • 入力が許可された範囲内にあることを検証します。
  • その後、ユーザーに行列の各要素を個別に入力するように促します。
  • 最後に、入力を検証するために入力された行列を出力します。

再帰的手法または LU 分解法の使用

このステップでは、行列の行列式を計算するための再帰的手法を実装します。前のプログラムを修正して、行列式の計算関数を追加します。

matrix_determinant.c ファイルを更新します。

nano matrix_determinant.c

前の内容を以下のコードに置き換えます。

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

#define MAX_SIZE 10

// 行列式を再帰的に計算する関数
int determinant(int matrix[MAX_SIZE][MAX_SIZE], int n) {
    int det = 0;
    int submatrix[MAX_SIZE][MAX_SIZE];

    // 1x1 行列のベースケース
    if (n == 1) {
        return matrix[0][0];
    }

    // 2x2 行列のベースケース
    if (n == 2) {
        return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
    }

    // より大きな行列の再帰的ケース
    int sign = 1;
    for (int k = 0; k < n; k++) {
        // 部分行列を作成する
        int subi = 0;
        for (int i = 1; i < n; i++) {
            int subj = 0;
            for (int j = 0; j < n; j++) {
                if (j == k) continue;
                submatrix[subi][subj] = matrix[i][j];
                subj++;
            }
            subi++;
        }

        // 再帰的計算
        det += sign * matrix[0][k] * determinant(submatrix, n - 1);
        sign = -sign;
    }

    return det;
}

int main() {
    int n, i, j;
    int matrix[MAX_SIZE][MAX_SIZE];

    // 行列の次元を読み取る
    printf("Enter the size of the square matrix (1-%d): ", MAX_SIZE);
    scanf("%d", &n);

    // 行列のサイズを検証する
    if (n < 1 || n > MAX_SIZE) {
        printf("Invalid matrix size. Please enter a size between 1 and %d.\n", MAX_SIZE);
        return 1;
    }

    // 行列の要素を読み取る
    printf("Enter the matrix elements:\n");
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            printf("Enter element [%d][%d]: ", i, j);
            scanf("%d", &matrix[i][j]);
        }
    }

    // 行列式を計算して出力する
    int det = determinant(matrix, n);
    printf("\nDeterminant of the matrix: %d\n", det);

    return 0;
}

プログラムをコンパイルして実行します。

gcc matrix_determinant.c -o matrix_determinant
./matrix_determinant

出力例:

Enter the size of the square matrix (1-10): 3
Enter the matrix elements:
Enter element [0][0]: 1
Enter element [0][1]: 2
Enter element [0][2]: 3
Enter element [1][0]: 4
Enter element [1][1]: 5
Enter element [1][2]: 6
Enter element [2][0]: 7
Enter element [2][1]: 8
Enter element [2][2]: 9

Determinant of the matrix: 0

再帰的な行列式計算に関する要点:

  • determinant() 関数は再帰的アプローチを使用して行列の行列式を計算します。
  • 1x1 および 2x2 の行列には、直接計算するベースケースがあります。
  • より大きな行列には、最初の行に沿った余因子展開の方法を使用します。
  • 関数は部分行列を作成し、それらの行列式を再帰的に計算します。

行列式の出力

この最後のステップでは、ユーザー体験を向上させるために、より詳細な出力とエラーハンドリングを追加して、行列の行列式を計算するプログラムを強化します。

matrix_determinant.c ファイルを更新します。

nano matrix_determinant.c

前の内容を以下の改良されたコードに置き換えます。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MAX_SIZE 10

// 行列式を再帰的に計算する関数
int determinant(int matrix[MAX_SIZE][MAX_SIZE], int n) {
    int det = 0;
    int submatrix[MAX_SIZE][MAX_SIZE];

    // 1x1 行列のベースケース
    if (n == 1) {
        return matrix[0][0];
    }

    // 2x2 行列のベースケース
    if (n == 2) {
        return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
    }

    // より大きな行列の再帰的ケース
    int sign = 1;
    for (int k = 0; k < n; k++) {
        // 部分行列を作成する
        int subi = 0;
        for (int i = 1; i < n; i++) {
            int subj = 0;
            for (int j = 0; j < n; j++) {
                if (j == k) continue;
                submatrix[subi][subj] = matrix[i][j];
                subj++;
            }
            subi++;
        }

        // 再帰的計算
        det += sign * matrix[0][k] * determinant(submatrix, n - 1);
        sign = -sign;
    }

    return det;
}

// 行列を整形して出力する関数
void print_matrix(int matrix[MAX_SIZE][MAX_SIZE], int n) {
    printf("\nMatrix:\n");
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            printf("%5d ", matrix[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int n, i, j;
    int matrix[MAX_SIZE][MAX_SIZE];
    bool valid_input = false;

    while (!valid_input) {
        // 行列の次元を読み取る
        printf("Enter the size of the square matrix (1-%d): ", MAX_SIZE);
        if (scanf("%d", &n)!= 1) {
            printf("Invalid input. Please enter a number.\n");
            while (getchar()!= '\n'); // 入力バッファをクリアする
            continue;
        }

        // 行列のサイズを検証する
        if (n < 1 || n > MAX_SIZE) {
            printf("Invalid matrix size. Please enter a size between 1 and %d.\n", MAX_SIZE);
            continue;
        }

        valid_input = true;
    }

    // 行列の要素を読み取る
    printf("Enter the matrix elements:\n");
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            printf("Enter element [%d][%d]: ", i, j);
            while (scanf("%d", &matrix[i][j])!= 1) {
                printf("Invalid input. Please enter an integer for element [%d][%d]: ", i, j);
                while (getchar()!= '\n'); // 入力バッファをクリアする
            }
        }
    }

    // 入力された行列を出力する
    print_matrix(matrix, n);

    // 行列式を計算して出力する
    int det = determinant(matrix, n);

    // 整形された行列式の出力
    printf("\n--- Determinant Calculation ---\n");
    printf("Matrix Dimension: %d x %d\n", n, n);
    printf("Determinant: %d\n", det);

    return 0;
}

プログラムをコンパイルして実行します。

gcc matrix_determinant.c -o matrix_determinant
./matrix_determinant

出力例:

Enter the size of the square matrix (1-10): 3
Enter the matrix elements:
Enter element [0][0]: 1
Enter element [0][1]: 2
Enter element [0][2]: 3
Enter element [1][0]: 4
Enter element [1][1]: 5
Enter element [1][2]: 6
Enter element [2][0]: 7
Enter element [2][1]: 8
Enter element [2][2]: 9

Matrix:
    1     2     3
    4     5     6
    7     8     9

--- Determinant Calculation ---
Matrix Dimension: 3 x 3
Determinant: 0

主な改良点:

  • 無効な入力を処理するための入力検証を追加しました。
  • 行列をより良いフォーマットで出力するための別の関数を作成しました。
  • 行列の次元と行列式を明確に表示するように出力を強化しました。
  • ユーザー入力に対するエラーハンドリングを改善しました。

まとめ

この実験では、C 言語で正方行列の次元と要素を読み取る方法を学びました。ユーザーが行列のサイズとその要素を動的に入力できるプログラムを作成しました。このプログラムは行列のサイズを検証し、その後ユーザーに行列の要素を入力するように促します。最後に、入力を検証するために入力された行列を出力します。

この実験の次のステップでは、再帰的手法または LU 分解法を使用して入力行列の行列式を計算する方法と、行列式を出力する方法を説明します。