Wyznacznik macierzy

0

Chciałbym stworzyć wyznacznik macierzy przez rozwinięcie Laplace, jednak nie wiem dlaczego mój algorytm (choć nie jest on zbyt optymalny) nie działa dla macierzy większych od 4x4. Co może być źle?
Oto kod:

 
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <stdio.h>
#include <math.h>
#include <string.h>
using namespace std;
#define ROZMIAR 5 //przy mniejszych niz 5 dziala
int wyznacznik(int ** macierz,int rozmiar,int suma,int a);
int det=0;
int main()
{
    det=0;
    srand(time(NULL));
    int **matrix = new int *[ROZMIAR];
    memset (matrix,0,ROZMIAR*sizeof(int));
    for (int i=0;i<ROZMIAR;i++)
    matrix[i]=new int [ROZMIAR];
    for (int i=0;i<ROZMIAR;i++)
    {
        for (int j=0;j<ROZMIAR;j++)
        {
            /* matrix[i][j]=2;
            if (i==j)
            matrix[i][j]=3;*/
            matrix[i][j]=rand() % 8 + 1;
            printf("%10d",matrix[i][j]);
        }
        cout<<endl<<endl;
    }
    cout<<endl<<endl;
    for (int i=0;i<=64;i++) cout<<'-';
    cout<<endl;
    wyznacznik(matrix,ROZMIAR,0,1);
    cout<<det<<endl;
    for (int i=0;i<ROZMIAR;i++)
    delete [] matrix[i];
    delete [] matrix;
    system("pause");
}
int wyznacznik(int **macierz,int rozmiar,int suma,int a)
{
    int n= rozmiar;
    int p=0,s=0,m=0,k=0,b=1;    // s - kolumna p - wiersz ktore skreslamy            k, m - kolumna i wiersz w nowej macierzy      b(dalej wrzucony jako parametr a w funkcji) jest wartoscia przez ktora mnozymy powstały przez skreslenie wyznacznik
    int ** minor = new int *[n-1];
    memset (minor,0,(n-1)*sizeof(int));
    for (int i=0;i<=n-1;i++)
    {
        minor[i]=new int [n-1];
        memset (minor[i],0,(n-1)*sizeof(int));
    }
    if (n==1)
    {
        suma = macierz[0][0];
        return suma;
    }
    else if (n==2) //wyznacznik 2x2
    {
        suma = suma + a*(macierz[0][0]*macierz[1][1]-macierz[0][1]*macierz[1][0]);
        return suma;
    }
    else if (n>2)
    {
        for (int s=0;s<n;s++)
        {
            for (int p=0;p<n;p++)
            {
                k=0;
                m=0;
                for (int i=0;i<n;i++)
                {
                    for (int j=0;j<n;j++)
                    {
                        if ( (i==s) || (j==p) )
                        {
                            if ((i==s) && (j==p))
                            {
                                b=macierz[i][j];
                                if ((i+j)%2==1)
                                b=b*(-1);
                            }
                            continue;
                        }
                        else
                        {
                            minor[k][m]=macierz[i][j];
                            m++;
                            if (m==n-1)
                            k++;
                        }
                    }
                    m=0;
                }
                suma=wyznacznik(minor,n-1,suma,b);
            }
            det+=a*suma;
            suma=0;
            return suma;
        }
    }
}
0

Strzelam, bo kilka miejsc wyjscia z funkcji, dla funkcji większej niż kilka linii to wg mnie zbrodnia!

obstawiam ten problem:

suma=0;
return suma; 

Większa analiza może kiedy indziej, bo to ładnie psuje całą resztę.

0

problemem jest to, że robisz to zbyt skomplikowane.
Podziel to na mniejsze części. Zrób funkcję:

  • stowMacierz
  • kopujMacierzMinorowa
  • usunMacierz
    Wówczas same obliczanie wyznacznika zrobi się bardziej czytelne i łatwiej będzie można ogarnąć na czym polega problem.
0

Mam wrażenie, że ten kod jest miejscami szerszy niż dłuższy.

0

Po radzie MarekR22 zmieniłem trochę program, aby można było więcej widzieć, tak więc:

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <stdio.h>
#include <math.h>
#include <string.h>
using namespace std;
#define ROZMIAR 5
int ** stworzMacierz(int rozmiar);
int ** zmniejszMacierz(int ** macierz,int rozmiar,int kolumna,int wiersz);
int wyznacznik(int ** macierz,int rozmiar,int suma,int a);
int det=0;
int main()
{
    det=0;
    srand(time(NULL));
    int ** matrix = stworzMacierz(ROZMIAR);
    cout<<endl<<endl<<endl;
    for (int i=0;i<ROZMIAR;i++)
    {
        for (int j=0;j<ROZMIAR;j++)
        {
            matrix[i][j]=rand() % 8 + 1;
            printf("%10d",matrix[i][j]);
        }
        cout<<endl<<endl;
    }
    cout<<endl<<endl;
    for (int i=0;i<=64;i++) cout<<'-';
    cout<<endl;
    wyznacznik(matrix,ROZMIAR,0,1);
    cout<<det<<endl;
    for (int i=0;i<ROZMIAR;i++)
    delete [] matrix[i];
    delete [] matrix;
    system("pause");
}
int wyznacznik(int **macierz,int rozmiar,int suma,int a)
{
    int n= rozmiar;
    int ** minor = stworzMacierz(n-1);
    int p=0,s=0,m=0,k=0,b=1;
    if (n==1)
        suma = macierz[0][0];
    else if (n==2)
        suma = suma + a*(macierz[0][0]*macierz[1][1]-macierz[0][1]*macierz[1][0]);
    else if (n>2)
    {        
// s - kolumna p - wiersz ktore skreslamy   
for (int s=0;s<n;s++)
            {
                for (int p=0;p<n;p++)
                {
                    b=macierz[s][p];
                    if ((s+p)%2==0)
                        b=b*(-1);
                    minor=zmniejszMacierz(macierz,n,s,p);
                    suma=wyznacznik(minor,n-1,suma,b);
                }
                det+=a*suma;
                suma=0;
        }

    return suma;
}
int ** zmniejszMacierz(int ** macierz,int rozmiar,int kolumna,int wiersz)
{
    int k=0,m=0;
    int n=rozmiar;
    int ** minor = stworzMacierz(n-1);
    for (int i=0;i<n;i++)
    {
        for (int j=0;j<n;j++)
        {
            if ( (i==wiersz) || (j==kolumna) )
            continue;
            else
            {
                minor[k][m]=macierz[i][j];
                m++;
                if (m==n-1)
                k++;
            }
        }
        m=0;
    }
    return minor;
}
int ** stworzMacierz(int rozmiar)
{
    int **matrix = new int *[rozmiar];
    memset(matrix,0,sizeof(int)*rozmiar);
    for (int i=0;i<rozmiar;i++)
    {
        matrix[i]=new int [rozmiar];
        memset(matrix[i],0,sizeof(int)*rozmiar);
    }
    return matrix;
}
 

Teraz program się zatrzymuje i wyświetla błąd, że program przestał działać.

0

Nieładna zmienna globalna det, niezwalniana pamięć zmniejszonej macierzy... To kolejne błędy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1