Newsgroup: it.comp.lang.c
Titolo: Codice calcoli matriciali

Saluti a tutti,
avrei bisogno di aiuto per scrivere un semplice programma che mi calcoli il
determinate e l'inversa di una matrice.
Su un libro ho trovato alcune scarne indicazioni che dicevano di
utilizzare una funzione ricorsiva per il calcolo del determinante, ma
non c'e' qualcosa di piu' semplice? Idem per il calcolo dell'inversa.
Con le ricorsive oltre al fattoriale non riesco ad andare :-)
Potreste fornirmi qualche indirizzo utile?
Ringrazio per l'aiuto (se poi qualcuno vuol mandarmi direttamente del
codice completo e' ben gradito  :-)))))
Roberto.
-- 
			  /:= Linux Powered =:/
  	    /:= e-mail: metti "libero" al posto di "NOSPAM" =:/

determinate e l'inversa di una matrice.
Dimenticavo: la matrice di ordine n variabile.



Per l'inversa non ho idea, per il determinante direi di applicare
l'algoritmo di kramer, secondo cui il determinante di una matrice di rango N
si calcola come somma dei prodotti tra gli elementi della prima riga e le
ridotte di rango N-1, con gli opportuni cambi di segno.
In questo modo procedi ricorsivamente fino ad avere ridotte di rango 1, il
cui determinante è uguale al valore dell'unico elemento.
Scusa la fraseologia probabilmente non corretta, ma è passato un po' di
tempo da quando studiavo queste cose ...
Ciao, Max.

Una volta trovato il determinante (per esempio come hai detto tu con
Kramer) la matrice inverse si trova calcolando per ogni elemento il
rapporto tra il complemento algebrico e il determinante stesso(che
ovviamente deve essere diverso da 0).
C'e' da dire  che al crescere della grandezza della matrice
probabilmente Kramer diventa poco adatto per calcolare il
determinante.
Paolo
--
pau...@freemail.it
--


Fermi pausa stop
l'algoritmo 'classico' per calcolo di determinante ed inversa di una
matrice funziona 'bene' solo se e' un essere umano a farlo e per matrici
di dimensione inferiore a 5 altrimenti si impazzisce prima di trovare la
soluzione!
per il calcolo numerico esistono algoritmi basati essenzialmente sulla
triangolarizzazione ( spero si scriva cosi! ) della matrice.
un ottimo punto di partenza e' il libro di calcolo numerico 'numerical
recipes' disponibile su 
www.nr.com
 ( vabbe' a rigori uno dovrebbe
acquistarlo ma per uso personale non penso se ne accorgano dell'uso dei
loro algoritmi )
oppure prova su netlib: 
http://ftp.unina.it:21006/
 altra raccolta si sw
di tipo numerico


 
--
pau...@freemail.it
--

semplicemente moltiplicando gli elementi della diagonale maggiore.
Aggiungo solamente due cose:
  1) E' importante durante il passo n-esimo di discesa nella
     triangolazione cercare la riga che ha l'elemento di
     modulo massimo alla colonna n (credo che si chiami variante
     pivot dell'algoritmo Gauss-Jordan).
     Se questo non viene fatto si possono avere veramente brutte
     sorprese calcolando determinanti di matrici in cui gli
     elementi hanno grandi differenze in modulo.
  2) Lo stesso algoritmo con l'aggiunta dei passi di risalita
     e lavorando su due matrici affiancate permette di calcolare
     direttamente l'inversa della matrice. In pratica si parte
     con la matrice identita' al fianco della matrice in input
     e durante la triangolazione si effettuano le operazioni
     di scalatura/composizione su entrambe le matrici.
     Finito anche la parte in risalita la matrice in input
     si sara' trasformata nella matrice identita' e la matrice
     identita' sara' diventata l'inversa della matrice in input.
HTH
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

Dimenticavo: la matrice di ordine n variabile.
Ti conviene ridurre la matrice ad una diagonale e fare il prodotto delle
righe. Ovviamente se scambi una riga con l'altra devi invertire il segno del
det.
Non sono sicuro che si il metodo migliore, senz'altro e' piu' efficente del
calcolo della matrice attraverso il calcolo dei determinanti dei minori di
una riga incrociata con la colonna .....
Per l'inversa procedi parallelamente sulla matrice identita' e su quella
nota, fino a ridurre quest'ultima all'identita. Se segui le stesse
operazioni su tutte e due, la matrice che prima era un'identita' diviene
l'inversa di quella di partenza.
Insomma conviene fare l'eliminazione di gaus...

Con le ricorsive oltre al fattoriale non riesco ad andare :-)
Penso che non ci siano alternative alle funzioni ricorsive. In pratica
devi scrivere la regola per cui riduci il calcolo di un determinante
di una matrice di ordine N al calcolo di N*(N-1)*...*1 (cioe n!)
determinanti di ordine 1 e con una funzione ricorsiva è abbastanza
semplice. Se trovo il listato del prog che avevo fatto te lo spedisco
Ciao
Gianluca

utilizzare una funzione ricorsiva per il calcolo del determinante
/******************
 * determ.c
 *
 * Andrea Laforgia
 *
 * 21 giu 1999
 ******************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void  inserisci (long ***, int ) ;
void  stampa (long **, int ) ;
long  determinante(long **, int );
void  distruggi ( long ***, int  ) ;
int main()
{
    long **a, n ;
    printf( "Introdurre la dimensione della matrice" ) ;
    scanf("%ld", &n) ;
    inserisci(&a, n) ;
    printf("\nMatrice introdotta: \n");
    stampa(a, n) ;
    printf("\ndeterminante: %ld\n", determinante(a, n) ) ;
    distruggi( &a, n ) ;
    return 0;
}
void inserisci(long ***a, int n)
{
    int i, j ;
    *a = malloc(n * sizeof(long *));
    for (i = 0; i < n; i++)
	(*a)[i] = malloc(n * sizeof(long));
    for (i = 0; i < n; i++) {
    	printf("Riga n. %d\n", i + 1);
	    for (j = 0; j < n; j++) {
	        printf("a[%d,%d] = ", i + 1, j + 1);
	        scanf("%ld", &((*a)[i][j]));
		}
    }
}
void stampa ( long **a, int n )
{
     int i, j;
     for (i = 0; i < n; i++) {
         for (j = 0; j < n; j++)
 	     printf("%2ld", a[i][j]);
 	 printf("\n");
     }
}
long **estratto ( long **a, int x, int n )
{
      long **b = malloc ( ( n-1 ) * sizeof ( int * ) ) ;
      int i, j, ki, kj ;
      for ( i = 0 ; i < n-1 ; i++ )
          b[i] = malloc ( (n-1) * sizeof ( int ) ) ;
      for ( i = 1, ki = 0 ; i < n ; i++, ki++ )
          for ( j = 0, kj = 0 ; j < n ; j++ )
              if ( j != x )
                 b [ki][kj++] = a[i][j] ;
      return b ;
}
long determinante(long **a, int n)
{
      int i ;
      long **p, dt = 0L ;
      if ( n == 1 ) return ( a[0][0] ) ;
      else
      {
         for ( i = 0 ; i < n ; i++ )
         {
             dt += a[0][i] * (long)pow(-1.0, i) *
                   determinante ( p = estratto ( a, i, n ), n-1 ) ;
             free ( p ) ;
         }
         return dt ;
      }
}
void distruggi ( long ***a, int n )
{
     int i ;
     for ( i = 0 ; i < n ; i++ )
         free ( (*a)[i] ) ;
     free ( *a ) ;
}
--
Andrea Laforgia (ICQ 87230455)
------------------------------ 
#exclude <windows.h>

  ******************/
[codice]
<sospiro>, il caro, vecchio (in senso buono) Laforgia, che postava
codice a raffica! :-)
Una sola preoccupazione: sarai mica di nuovo disoccupato?
-- 
 Ciao, Bianco.
 Reply to luca.bianco (at) 
tiscalinet.it

l'inversa di quella di partenza.
Lavorando di carta e matita credo di aver capito come funziona il metodo
per la triangolarizzazione della matrice.
Ora devo vedere come riuscire a diagonalizzare la matrice.
Ci provero'. Se giungero' ad una soluzione accettabile postero' il
codice se interessa.
Grazie mille
Saluti
Roberto.


gentilissimo La Forgia (che ringrazio) comincio a capire qlcosa.
	      ^^^^^^^^^
Ops...... pardon :-)
Ho sbalgiato a scrivere il cognome


Una sola preoccupazione: sarai mica di nuovo disoccupato?
eh eh eh ... no, solo un po' nostalgico... :)
