Как узнать обратную матрицу NXN в C

Привет всем, я внес некоторые изменения в код, чтобы его было легко понять, выглядит то, что у меня есть до сих пор, я сохранил прототип функции в начале кода, и он отлично работает, но он просто работает нормально, когда я пробую 2x2 матрица, потому что, если я попробую матрицу 3x3, 4x4 или 6x6, она не работает нормально, определитель вычисляется неправильно, я думаю, это проблема определителя, но я не знаю, как ее решить. Вот код.

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


float determinant(int tam,float [][tam]);

void cofactor(int tam,float [][tam]);

void transpose(int tam,float [][tam],float [][tam]);

int validate(){

    int val;
    char *buf = (char *) malloc(10);

    memset(buf,0,10);

    while(fgets(buf, 10, stdin) != NULL ){
        if(buf[0]!='\n') {
            val = atoi(buf);
            break;
        }
    }
    free(buf);

    return val;
}

float determinant(int tam, float matrix[][tam])
{


    float s = 1, det = 0, b[tam][tam];

    int i, j, m, n, c;

    if (tam == 1)

      {

       return (matrix[0][0]);

      }

    else

      {

       det = 0;

       for (c = 0; c < tam; c++)

         {

          m = 0;

          n = 0;

          for (i = 0;i < tam; i++)

            {

              for (j = 0 ;j < tam; j++)

                {

                  b[i][j] = 0;

                  if (i != 0 && j != c)

                   {
                     b[m][n] = matrix[i][j];

                     if (n < (tam - 2))

                      n++;

                     else

                      {

                       n = 0;
                       m++;

                       }

                     }

                 }

               }

            det = det + s * (matrix[0][c] * determinant( tam - 1,b));
            s = -1 * s;
            }
      }

      return (det);
}


 void cofactor( int tam,float num[][tam])

 {

   float b[tam][tam], fac[tam][tam];

    int p, q, m, n, i, j;

    float x = 0;


  for (q = 0;q < tam; q++)

  {

    for (p = 0;p < tam; p++)

    {

     m = 0;

     n = 0;

 for (i = 0;i < tam; i++)

 {

   for (j = 0;j < tam; j++)

    {

      if (i != q && j != p)

      {
        b[m][n] = num[i][j];

        if (n < (tam - 2))

         n++;

        else

         {

           n = 0;

           m++;

           }

        }

    }

  }

  x = pow(-1, q + p) * determinant( tam - 1,b);

  fac[p][q] = x;
}

}

 transpose(tam,num, fac);

}

  void transpose(int tam,float num[][tam], float fac[][tam])

 {

  int i, j;

  float b[tam][tam], inverse[tam][tam], d;



   for (i = 0;i < tam; i++)



  {

     for (j = 0;j < tam; j++)

       {

         b[i][j] = fac[j][i];

        }

    }

      d = determinant(tam,num);



     for (i = 0;i < tam; i++)

    {

     for (j = 0;j < tam; j++)

       {

        inverse[i][j] = b[i][j] / d;

        }

    }

       printf("\n\n\nThe inverse of matrix is : \n");

       for (i = 0;i < tam; i++)

    {

     for (j = 0;j < tam; j++)

       {

         printf("\t%f", inverse[i][j]);

        }

        printf("\n");

     }

}

    int verify_Size(int line){

        if((line > 0) && (line <= 6))
        {
            return 1;
        }

    return 0;
    }


    int create_Matrix(int LINE){

        int matrix[LINE][LINE];
        float aux[LINE][LINE];

        printf("\n\n\nPle:", (LINE * LINE));
        printf("\n--------------------------------\n");

        for(int i=0;i<LINE;i++)
        {
            for(int j=0;j<LINE;j++)
            {
                printf("Value[%d][%d]: ",i,j);

                matrix[i][j] = validate();
            }
        }

        printf("\n\nYour Bidimensional Matrix is:");
        printf("\n--------------------------------\n");


        for(int i=0;i < LINE;i++)
        {
            for(int j=0; j< LINE;j++)
            {
                printf("\t%2d",matrix[i][j]);
                aux[i][j] = (float) matrix[i][j];

        }
        printf("\n");
    }

      float d = determinant(LINE,aux);

       printf("\n\nDeterminante Main: %f \n",d);

       if (d == 0)

       printf("\nInverse of Entered Matrix is not possible\n");

       else

        cofactor(LINE,aux);

       return 0;

}


    int main(){

    int flag,line;

    do{
        printf("Enter the order of the Matrix:\n");
        printf("-------------------------------\n");

        printf("Lines: ");
        line = validate();


        if(verify_Size(line)== 1)
        {
            create_Matrix(line);

        }else{

            printf("\nMatrix must to be till 6 X 6!\n");

            flag = 0;

        }

    }while(flag != 1);

    return 0;
}

person Rafael Rossales    schedule 18.09.2020    source источник
comment
I want to remove the function's prototype at the beginning Почему?   -  person dxiv    schedule 19.09.2020
comment
Потому что у меня есть функция, которая позволяет пользователю создать матрицу NxN, так что я не знаю размер матрицы до того, как пользователь создаст матрицу.   -  person Rafael Rossales    schedule 19.09.2020
comment
Код, который вы разместили, выглядит жестко запрограммированным на 3x3. Возня с прототипами этого не изменит.   -  person dxiv    schedule 19.09.2020
comment
Да, это идея, я хочу удалить прототип и передать матрицы в качестве параметров, пока не найду обратную матрицу.   -  person Rafael Rossales    schedule 19.09.2020
comment
Я бы начал с запуска вашего кода через средство форматирования. Для начала я попытался получить все это в блоке кода уценки.   -  person ggorlen    schedule 19.09.2020


Ответы (1)


Похоже, вы находите обратную матрицу по правилу Крамера. Хотя это работает нормально для размеров матрицы 2x2 или 3x3, сложная часть реализации правила Крамера обычно заключается в оценке детерминант. Если вы вычисляете детерминант NxN, следуя определению, вычисление является рекурсивным и имеет факториальную вычислительную сложность O(N!) (Википедия).

Предлагаю перейти на другой алгоритм. LUP-факторизация выполняется быстро и относительно просто, и в Википедии есть пример реализации.

person Pascal Getreuer    schedule 19.09.2020