PDA

View Full Version : [c++]: dove sta l'errore in questo listato?


vermaccio
27-03-2006, 11:24
problema risolto.
vedere
http://www.hwupgrade.it/forum/showthread.php?t=1168051
per l'algoritmo
"prodotto di due matrici di grandezza qualsiasi"


!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!







questo programma effettua il prodotto tra due matrici A, B e crea la matrice C=A*B

1)trovate l'errore per cui non funziona l'intestazione della funzione (la funzione è corretta se messa nel main ma messa esternamente in una funzione come ho fatto c'è errore di compilazione)
.
2)consigliate modifiche al programma per fare la stessa cosa in maniera più ottimizzata
3)in ingresso dico alla funzione anche quante righe e colonne hanno le matrici A e B che sono array. esiste un modo per estrarre il numero di "righe2 e "colonne" dall'array? ad esempio avendo un array "D=[a][b]", si può sapere quante righe "a" e colonne "b" è?


nota:le matrici A, B, C sono GLOBAL e devono essere modificate dalla funzione. già qui ho il dubbio se, per come ho scritto l'intestazione della funzione, in realtà sto creando due matrici locali e non sto mettendo i risultati dei calcoli nella globali)

listato:



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

double C [6][4];
double A [6][3]= { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}, {13, 14, 15}, {16, 17, 18} };
double B [3][4]= { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };
double test;
int i,j,k;
double righeA, colonneA, righeB, colonneB;


//--------------------
//funzione
void prodottomatrici(double matA, double righeA, double colonneA , double matB, double righeB, double colonneB, double matC)
{
for (i=0; i<6; i++){
for (j=0; j<4; j++){
C[i][j]=0;
for (k=0; k<3; k++){
C[i][j]=C[i][j]+A[i][k]*B[k][j];
//test=A[i][k]*B[k][j];
//printf("%g\n", test );
}
printf("%g\n", C[i][j] );
}
}
}



//--------------------
void main(void)
{

prodottomatrici(A,6,3,B,3,4,C);

//stampa a video 2 elementi per test
printf("elemento C[1][1]: %g\n", C[0][0] );
printf("elemento C[4][4]: %g\n", C[3][3] );
//deve venire 38 e 272




}

andbin
27-03-2006, 12:29
Il problema principale nel sorgente è il passaggio degli array alla funzione prodottomatrici.
Bisogna ricordare innanzitutto che quando si passa un array (a 1, 2, ... n dimensioni) ad una funzione, non si passa l'intero array per valore ma solo il puntatore al primo elemento dell'array.

Se si ha un array:
double A [6][3] = { ... };
ci sono diversi modi per dichiarare il parametro della funzione:
a) double arr[6][3]
b) double arr[][3]
c) double (*arr)[3]
In ogni caso, la funzione non può conoscere la dimensione totale dell'array basandosi solo su questo argomento. Ad esempio facendo sizeof(arr) si ottiene 4 (la dimensione tipica di un puntatore).

vermaccio
27-03-2006, 13:09
anche mettendo nella dichiarazione della funzione

void prodottomatrici(double matA[6][4], double righeA, double colonneA , double matB[3][4], double righeB, double colonneB, double matC[6][4]) {


non funziona :(

appare il messaggio (visual studio .net)

error C2664: 'prodottomatrici' : cannot convert parameter 1 from 'double [6][3]' to 'double [][4]'

come risolvo?


listato modificato--------------








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

double C [6][4];
double A [6][3]= { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}, {13, 14, 15}, {16, 17, 18} };
double B [3][4]= { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };
double test;
int i,j,k;
double righeA, colonneA, righeB, colonneB;


// PROGRAMMA PRINCIPALE ---------





//funzione
void prodottomatrici(double matA[6][4], double righeA, double colonneA , double matB[3][4], double righeB, double colonneB, double matC[6][4]) {

//i=righeA
//j=colonneB)
//k=colonneA=righeB

for (i=0; i<6; i++){
for (j=0; j<4; j++){
matC[i][j]=0;
for (k=0; k<3; k++){
matC[i][j]=matC[i][j]+matA[i][k]*matB[k][j];
//test=A[i][k]*B[k][j];
//printf("%g\n", test );
}
printf("%g\n", matC[i][j] );
}
}
}



void main(void)
{

prodottomatrici(A,6,3,B,3,4,C);

printf("elemento C[1][1]: %g\n", C[0][0] );
printf("elemento C[4][4]: %g\n", C[3][3] );





}


ps: ma matrC "locale" della funzione come fa apassare il risultato alla C globale con cui abbiamo richiamato la funzione?

andbin
27-03-2006, 13:20
anche mettendo nella dichiarazione della funzione

void prodottomatrici(double matA[6][4], double righeA, double colonneA , double matB[3][4], double righeB, double colonneB, double matC[6][4]) {


non funziona :(Dal listato mi risulta che l'array A è stato dichiarato double A [6][3] e non [6][4].

ps: ma matrC "locale" della funzione come fa apassare il risultato alla C globale con cui abbiamo richiamato la funzione?Come ripeto, quando si passa un array ad una funzione si passa l'indirizzo del primo elemento. Se passi l'array C alla funzione, il parametro matrC contiene il puntatore al primo elemento di C. Essendo un puntatore, logicamente, puoi accedere al contenuto dell'array e leggere/scrivere nell'array.

vermaccio
27-03-2006, 13:49
Dal listato mi risulta che l'array A è stato dichiarato double A [6][3] e non [6][4].


opps! sono proprio un vermaccio! non me ne ero accorto!!!

grazie
ora funziona

:)

vermaccio
27-03-2006, 16:22
ma posso passare alla funzione una matrice senza definire quanto è grande nell'intestazione della funzione?

es: ipotizziamo di avere

void prodottomatrici(double matA[4][4], double righeA, double colonneA , double matB[4][4], double righeB, double colonneB, double matC[4][4]) {
[...]
}


io, invece vorrei che al posto di matrici di grandezza fissata 4X4 (in questo esempio) double matA[4][4], double matB[4][4], double matC[4][4] io abbia matricI matA, matB, matC generiche e quando richiamo la funzione gli spedisco una matrice grosse come mi pare.

altrimenti posso passartgli solo matrici 4X4 mentre vorrei passargli matrici grandi a piacere. la loro dimensione la specifico con "righeA, colonneA, righeB, colonneB".

Se non faccio così ogni volta che moltiplico tra loro matrici di dimensioni diverse devo scrivere una funzione apposita!!!!!!!


io vorrei cioè creare una funzione che, se gli do in pasto due matrici MAT1=aXb e MAT2=bXc mi fa il loro prodotto e mi restituisce una matrice aXc:

la funzione la attiverei insomma con:

(nel main)
prodottomatrici(MAT1, a, b , MAT2, b, c, MATRICEPRODOTTO);



si può fare?
logicamente nei cicli interni "for" metto

or (i=0; i<a; i++){
for (j=0; j<c; j++){


il mio problema, ripeto, è l'intestazione della funzione, non il contenuto.

vermaccio
27-03-2006, 16:42
Se ad esempio devo moltiplicare una matrice 3X4 e una 4X3 e poi una 4X5 con una 5X4 vorrei poter usare la stesa function senza dover scrivere 2 function distinte con in ingresso

void prodottomatrici(double matA[4][3], double righeA, double colonneA , double matB[3][4], double righeB, double colonneB, double matC[4][4]) {
[...]
}

e

void prodottomatrici(double matA[4][5], double righeA, double colonneA , double matB[5][4], double righeB, double colonneB, double matC[4][4]) {
[...]
}

andbin
27-03-2006, 16:55
ma posso passare alla funzione una matrice senza definire quanto è grande nell'intestazione della funzione?

es:

void prodottomatrici(double matA[4][4], double righeA, double colonneA , double matB[4][4], double righeB, double colonneB, double matC[4][4]) {

//i=righeA
//j=colonneB
//k=colonneA=righeB !!!!!!! se colonneA diverso da righeB si ha errore

for (i=0; i<6; i++){
for (j=0; j<4; j++){
matC[i][j]=0;
for (k=0; k<3; k++){
matC[i][j]=matC[i][j]+matA[i][k]*matB[k][j];
//test=A[i][k]*B[k][j];
//printf("%g\n", test );
}
//printf("%g\n", matC[i][j] );
}
}


}


insomma invece che double matA[4][4], double matB[4][4], double matC[4][4] posso scrivere matriceA, B, c generiche e quando richiamo la funzione gli spedisco una matrice grosse come mi pare?
Diciamo che la risposta sarebbe nì (un si e un no, pressappoco).

Il problema in sostanza è il seguente. Come ho già detto in questo 3d, se si ha un array del tipo:

double A [6][3] = { ... };

Il parametro della funzione può essere dichiarato in questi modi:
a) double arr[6][3]
b) double arr[][3]
c) double (*arr)[3]

Cosa si può notare?? Il numero di colonne ([3] nell'esempio sopra) è sempre dichiarato. Il compilatore DEVE sempre conoscere quante colonne ci sono nell'array bidimensionale perché con questo valore è in grado, sfruttando l'aritmetica dei puntatori, di accedere alla cella [i][j].
Nella funzione, quando si fa arr[i][j], il compilatore è quindi in grado di "tradurre" questa istruzione in un qualcosa del tipo (spero di scriverlo giusto):

*(((double*) arr) + i*3 + j)

A questo punto si capisce bene che usando il solo argomento per il passaggio dell'array NON è possibile passare un array bidimensionale di dimensione qualsiasi, cioè con un numero di righe/colonne arbitrario.

In realtà la scappatoia ci sarebbe ma devi fare delle modifiche. In pratica devi fare tu quello che farebbe il compilatore per accedere ad una cella.

Esempio:

double a[5][8] = { .... };

void funzione (double *arr, int nrig, int ncol)
{
int i, j; /* i due indici */
double elem;

....
elem = *(arr + i * ncol + j);
}

per chiamare la funzione si usa quindi, per esempio:
funzione (&a[0][0], 5, 8);

Spero, naturalmente, di aver spiegato la cosa in modo abbastanza chiaro! ;)

P.S.: ho notato che passi alla funzione le dimensione tramite dei double. Non vedo per quale motivo devi passare dei double quando puoi tranquillamente passare degli int. Dopotutto le dimensioni sono dei numeri interi!

vermaccio
27-03-2006, 17:10
passo dei double perchè prima di affinare il codice volevo risolvere questo problemino.

comunque.
non mi è molto chiaro nel caso devo passare due matrici:

Se abbiamo due matrici
double matA[5][8] = { .... };
double matB[8][3] = { .... };

come definisco l'intestazione della function?
(gli passo il numero di righe e colonne (5,8,8,3) delle due matrici matA e matB, la matrice "risultato" matC e, se ho ben capito, i puntatori alle due matrici, ma come lo scrivo?)

void funzione (...come lo scrivo?...)
{
int i, j; /* i due indici */

double elementomatriceA, elementomatriceB;

[...]
//se devo fare matC[x][y]=matA[i][j]+matB[m][n]
//un elemento di matriceA[i][j]
elementomatriceA= ... come lo definisco?
//un elemento di matriceB[m][n]
elementomatriceB= ... come lo definisco?



}


grazie per l'infinita pazienza che stai dimostrando :)

andbin
27-03-2006, 17:23
passo dei double perchè prima di affinare il codice volevo risolvere questo problemino.

comunque.
non mi è molto chiaro nel caso devo passare due matrici:

Se abbiamo due matrici
double matrA[5][8] = { .... };
double matrB[8][3] = { .... };

come definisco l'intestazione della function?
(gli passo il numero di righe e colonne (5,8,8,3) delle due matrici matA e matB, la matrice "risultato" matC e, se ho ben capito, i puntatori alle due matrici, ma come lo scrivo?)

void funzione (...come lo scrivo?...)
{
int i, j; /* i due indici */

double elementomatriceA, elemento matriceB;

[...]
//se devo fare matC[x][y]=matA[i][j]+matB[m][n]
//elemento matA[i][j]
...come lo definisco?
//elemento matB[m][n]
...come lo definisco?



}
Faccio un esempio completo:
double matrA[5][8] = { .... };
double matrB[8][3] = { .... };
double matrC[N][M];

/* Metti tu N ed M, io non so quanto deve essere
per ottenere il prodotto delle matrici,
non me ne intendo :p */

void funz (double *matrA, int nrigA, int ncolA, double *matrB, int nrigB, int ncolB, double *matrC, int nrigC, int ncolC)
{
int iA, jA;
int iB, jB;
int iC, jC;
double elemA, elemB, elemC;

....
elemA = *(matrA + iA * ncolA + jA);
elemB = *(matrB + iB * ncolB + jB);

elemC = .... metti il tuo calcolo ....

*(matrC + iC * ncolC + jC) = elemC;
....
}

/* dal main */
funz (&A[0][0], 5, 8, &B[0][0], 8, 3, &C[0][0], N, M);

grazie per l'infinita pazienza che stai dimostrando :)prego, non c'e problema. ;)

vermaccio
27-03-2006, 17:26
tu hai scritto:

elem = *(arr + i * ncol + j);

il * più esterno indica indirizzo.
invece quello dentro è un prodotto, giusto?

elem è l'elemento della matrice arr[i][j] che passato alla funzione solo come puntatore *arr.

è così?

quindi dovrebbe essere

void funzione (double *matA, *matB, int nrigA, int ncolA, int nrigB, int ncolB)
{
int i, j, m,n;
// i,j indici di matrice A
//m,n indici di matrice B
double elem;

....
elemento_i_j_matrA= *(matA + i * ncolA + j);
elemento_m_n_matrB= *(matB + m * ncolB + n);
}

è così^?

ma
*(matA + i * ncolA + j);
indica il puntatore a cosa?

vermaccio
27-03-2006, 17:27
sei stato più rapido di me:)

mi serve solo sapere il significato di *(bla bla bla) che metti dentro per trovare un elemento

andbin
27-03-2006, 19:32
L'operatore * oltre ad essere l'operatore aritmetico della moltiplicazione, è anche l'operatore di "dereferenziazione" di un indirizzo. Dato un indirizzo, l'operatore * permette di accedere al valore puntato dall'indirizzo. Il tipo di dato puntato ovviamente deve essere dichiarato!

Esempio:
int a = 20; /* un intero */
int *ptr_a = &a; /* un puntatore ad intero ... che punta subito ad a */

*ptr_a quindi vale 20Così ti è più chiaro?

Nota che le parentesi tonde non centrano con la dereferenziazione. Nel mio esempio degli array *(matrA + iA * ncolA + jA) le parentesi servono per raggruppare una espressione. Il risultato di questa espressione (un indirizzo quindi) viene poi dereferenziato.

vermaccio
27-03-2006, 23:16
ok.
ma non ho capito perchè deferenziando
(matrA + iA * ncolA + jA) ,ovvero facendo *(matrA + iA * ncolA + jA), si ottiene elementoA della matrice A.



se abbiamo una matrice A che in realtà è un array di array [i][j], un suo elemento è, ad esempio, l'elemento [i][j]-esimo dell'array.
perchè ha indirizzo *(matrA + iA * ncolA + jA)??

matrA (che era stato passato alla function come indirizzo tramite la "void funz (double *matrA,...") è l'indirizzo del primo elemento dell'array di array quindi è l'indirizzo dell'elemento [0][0] dell'array. Se non ho detto una fesseria ed è vero, allora sommare (iA*ncolA) e JA che effetto ha?

La matrice A è un array di array quindi lo possiamo vedere anche, detto in modo gezzo, come una matrice di cellette cui è associato sia il valore dell'elemento della matrice relativo alla cellatte sia l'indirizzo della celletta nell'array. Un elemento [i][j] che indirizzo ha?


:confused:


infine:
*ptr_a = &a

*ptr_a deferenzia il puntatore ad a.
ma &a cosa indica? il valore di a?

cioè è come avere una scatola chiamata "a".
l'etichetta è l'indirizzo della scatola (dove sta nello scaffale).
il contenuto è il valore ovvero cosa c'è nella cscatola (quanto vale "a").

&scatola sarebbe il contenuto della scatola "a"
prt_a è l'indirizzo
*ptr_a il contenuto della scatola puntata dal puntatore prt_a ovvero "a"

è esatto?

ma se così è allora quando dichiaro una variabile

a=2

io in realtà sto dicendo &a=2 cioè il contenuto della scatola a è "2"?

andbin
28-03-2006, 09:14
ok.
ma non ho capito perchè deferenziando
(matrA + iA * ncolA + jA) ,ovvero facendo *(matrA + iA * ncolA + jA), si ottiene elementoA della matrice A.



se abbiamo una matrice A che in realtà è un array di array [i][j], un suo elemento è, ad esempio, l'elemento [i][j]-esimo dell'array.
perchè ha indirizzo *(matrA + iA * ncolA + jA)??

matrA (che era stato passato alla function come indirizzo tramite la "void funz (double *matrA,...") è l'indirizzo del primo elemento dell'array di array quindi è l'indirizzo dell'elemento [0][0] dell'array. Se non ho detto una fesseria ed è vero, allora sommare (iA*ncolA) e JA che effetto ha?

La matrice A è un array di array quindi lo possiamo vedere anche, detto in modo gezzo, come una matrice di cellette cui è associato sia il valore dell'elemento della matrice relativo alla cellatte sia l'indirizzo della celletta nell'array. Un elemento [i][j] che indirizzo ha?


:confused:


infine:
*ptr_a = &a

*ptr_a deferenzia il puntatore ad a.
ma &a cosa indica? il valore di a?

cioè è come avere una scatola chiamata "a".
l'etichetta è l'indirizzo della scatola (dove sta nello scaffale).
il contenuto è il valore ovvero cosa c'è nella cscatola (quanto vale "a").

&scatola sarebbe il contenuto della scatola "a"
prt_a è l'indirizzo
*ptr_a il contenuto della scatola puntata dal puntatore prt_a ovvero "a"

è esatto?

ma se così è allora quando dichiaro una variabile

a=2

io in realtà sto dicendo &a=2 cioè il contenuto della scatola a è "2"?
No, alt .... facciamo chiarezza!

Nel linguaggio C/C++ ci sono 2 operatori per la gestione degli indirizzi:
- l'operatore & per reperire l'indirizzo di una variabile
- l'operatore * per reperire il valore di una variabile dato il suo indirizzo

Quindi:
int a = 14;
Dire &a significa "indirizzo di a".

int *pa;
pa è un "puntatore ad un intero" (quindi il valore di pa deve essere un indirizzo).

Da queste ne deriva che puoi fare:
int *pa = &a;

A questo punto, dopo queste assegnazioni, che tu dica a oppure *pa, entrambi "valgono" 14.
Un po' più chiaro adesso?

Veniamo al problema dell'array bidimensionale.
Sei d'accordo con me che se dichiari il parametro della funzione come array bidimensionale, sei costretto a dichiarare almeno il numero delle colonne?
Come ho già spiegato, il parametro della funzione può essere dichiarato in uno di questi modi (non so se ce ne sono altri, ma se ci fossero sarebbero alquanto "bizzarri" quasi quanto il terzo modo):
a) double arr[6][3]
b) double arr[][3]
c) double (*arr)[3]

Usando un parametro arr come sopra, dentro la funzione puoi usare senza problemi l'espressione arr[i][j]. Il compilatore sapendo che è un array bidimensionale, implementa lui l'aritmetica dei puntatore per accedere alla cella voluta.

Se il tuo problema è quello di voler passare un array bidimensionale qualsiasi, non puoi più usare il modo sopra ma fare tu e ripeto TU, quello che farebbe il compilatore.
Un array, indipendentemente dal numero di dimensioni, fisicamente è memorizzato (in memoria) come un array lineare di celle.
Quindi tu dichiarando un double *matrA, dichiari un semplice puntatore a un double e devi applicare tu l'aritmetica dei puntatori per accedere alla cella voluta.

Esempio pratico in memoria (nota che i double sono tipicamente lunghi 8 byte).

double A[2][3] = { { 3,5,8 }, { 2,6,4 } };

double *pa = &A[0][0];

Dal punto di vista "logico" hai:
+---+---+---+
| 3 | 5 | 8 |
+---+---+---+
| 2 | 6 | 4 |
+---+---+---+

Supponiamo che A parta dall'indirizzo 1000. Dal punto di vista fisico (in memoria) hai 6 double in sequenza memorizzati così:
Indirizzo valore
1000 3
1008 5
1016 8
1024 2
1032 6
1040 4
(quindi pa vale 1000)

dire A[i][j] è quindi equivalente a dire *(pa + i*3 + j).

vermaccio
28-03-2006, 11:25
Nel linguaggio C/C++ ci sono 2 operatori per la gestione degli indirizzi:
- l'operatore & per reperire l'indirizzo di una variabile
- l'operatore * per reperire il valore di una variabile dato il suo indirizzo

Quindi:
int a = 14;
Dire &a significa "indirizzo di a".


ehm...
ma se <<l'operatore & per reperire l'indirizzo di una variabile>> allora "&a" è l'indirizzo della variabile a.

Se "pa" è l'indirizzo di a, poichè <<l'operatore * per reperire il valore di una variabile dato il suo indirizzo>>
allora "*pa" è la variabile ed infatti tu dichiari la variabile "int *pa" ovvero dichiari la variabile intera "a" che sta all'indirizzo pa

MA (e se chiarisco questo ho capito :) )
come posso dire
int *pa = &a;
????

il membro a sinistra "int *pa" indica la variabile a tramite la deferenziazione del suo indirizzo pa.

il membro a destra "&a" indica l'indirizzo di a.

che senso ha scrivere l'uguaglianza
int *pa = &a;
se cosa sta a sinistra non è omogeneo con cosa sta a destra?
a sinistra ho una variabile.
a destra un indirizzo.

int *pa = &a;
equivale a dire
int a = &a;

cioè dici che a è uguale al suo indirizzo?????

?

andbin
28-03-2006, 11:44
ehm...
ma se <<l'operatore & per reperire l'indirizzo di una variabile>> allora "&a" è l'indirizzo della variabile a.Perfetto. :)

Se "pa" è l'indirizzo di a, poichè <<l'operatore * per reperire il valore di una variabile dato il suo indirizzo>>
allora "*pa" è la variabile ed infatti tu dichiari la variabile "int *pa" ovvero dichiari la variabile intera "a" che sta all'indirizzo pa

MA (e se chiarisco questo ho capito :) )
come posso dire
int *pa = &a;
????

il membro a sinistra "int *pa" indica la variabile a tramite la deferenziazione del suo indirizzo pa.

il membro a destra "&a" indica l'indirizzo di a.

che senso ha scrivere l'uguaglianza
int *pa = &a;
se cosa sta a sinistra non è omogeneo con cosa sta a destra?
a sinistra ho una variabile.
a destra un indirizzo.

int *pa = &a;
equivale a dire
int a = &a;

cioè dici che a è uguale al suo indirizzo?????

?Precisazione:

Dichiarare:
int *pa;
significa dichiarare una variabile pa che è "un puntatore ad un intero". Nella dichiarazione, il * sta per puntatore.

Una variabile "puntatore" contiene un indirizzo.

Quindi la dichiarazione:
int *pa = &a;
significa "assegnare l'indirizzo di a alla variabile puntatore pa"

Nota che il = non significa uguaglianza ma assegnamento.

Quando fai:
int a = 2;
non vuol dire che a è uguale a 2 ma che hai assegnato 2 ad a!!!

vermaccio
28-03-2006, 12:14
perfetto!
sei stato illuminante.
tra oggi e domani cerco di scrivere quell'algoritmo e poi ti faccio sapere.

visto il tuo contributo te lo incollo qui se funziona. un algoritmo che serve a moltiplicare due matrici di dimensioni qualsiasi fa sempre comodo.

nota per te:

se hai due matrici
A[a][b]
B[m][n]

per moltiplicare A*B
DEVE essere b=m
e la matrice che si ottiene è
C[a][n]=A*B


logicamente B*A è DIVERSO da A*B

B*A=D[m][b] ma deve essere n=a

andbin
28-03-2006, 12:28
Qualcosa sulle matrici l'avevo sicuramente studiato in un passato molto ... remoto. Attualmente in matematica sono moooolto arruginito!!! ;)

Comunque la mitica Wikipedia ancora una volta viene in (mio) aiuto:
http://it.wikipedia.org/wiki/Moltiplicazione_di_matrici

vermaccio
28-03-2006, 15:01
qualcosa non va, credo:

tu hai detto
<<

double A[2][3] = { { 3,5,8 }, { 2,6,4 } };

double *pa = &A[0][0];

Dal punto di vista "logico" hai:
+---+---+---+
| 3 | 5 | 8 |
+---+---+---+
| 2 | 6 | 4 |
+---+---+---+

Supponiamo che A parta dall'indirizzo 1000. Dal punto di vista fisico (in memoria) hai 6 double in sequenza memorizzati così:
Indirizzo valore
1000 3
1008 5
1016 8
1024 2
1032 6
1040 4
(quindi pa vale 1000)

dire A[i][j] è quindi equivalente a dire *(pa + i*3 + j).
>>

Facciamo un esempio per vedere che esce fuori

elemento in matrice[1][1]=(3) = essendoarray = A[0][0] =*(pa + i*3 + j)=*(1000+0+0)=*(100) : ok.

elemento in matrice[2][3]=(4) = essendoarray = A[1][2] =*(pa + i*3 + j)= *(1000+1*3+2)=*(1005) : NO!

qualcosa non va. dove è che nella "formulina2 c'è il salto di 8 bit in 8 bit?

ogni riga, essendo la matrice di j colonne, occupa 8*j bit
avendo matrice [2X3] cioè j=3
inizio riga1: 1000
fine riga1: 1000+8*3-1=1023
primo elemento riga2: 1000+8*3=1024

quindi se sto in i-esima riga io devo andare "avanti" di i*(8*j) per trovare primo elemento di riga i-esima

+---+---+---+
| X | X | X |
+---+---+---+
| 2 | 6 | 4 |
+---+---+---+

se salto tutta prima riga perchè voglio eelemento in seconda riga

una volta che sono sulla riga i-esima devo spostarmi sull'elemnto che voglio di quella riga e vado a vedere in che colonna j sto: ogni "posto" (colonna) che avanzo io avanzo di 8 bit quindi +8*j

+---+---+---+
| X | X | x |
+---+---+---+
| X | 6 | 4 |
+---+---+---+

se mi fermo al secondo elemento della seconda riga


quindi *(1000+i*(8*j)+8*j)=
*(1000+8*i*j+8*j)

riapplichiamo "*(1000+8*i*j+8*j)" all'esempio che in altro non funzionava per vedere se è corretto:

Supponiamo che A parta dall'indirizzo 1000.
*pa=1000
(quindi pa vale 1000)

elemento in matrice[1][1]=(3) = essendoarray = A[0][0] =*(pa+8*i*j+8*j)=*(1000+8*0*0+8*0)=*(100) : ok.

elemento in matrice[2][3]=(4) = essendoarray = A[1][2] =*(pa+8*1*2+8*2)= *(1000+16+16)=*(1032) : OK!

Indirizzo valore
1000 3
1008 5
1016 8
1024 2
1032<-- 6 <--eccolo!
1040 4



confermi?

andbin
28-03-2006, 15:36
AAAAAAAAAAAALT! ;)

C'è una cosa che probabilmente non sai e che io non ho pensato di spiegarti.
Supponendo sempre, come è il caso tipico, che un double sia lungo 8 bytes:

double *pa; /* supponiamo che pa valga 1000 */

pa = pa+1; /* Incremento il puntatore di 1 */

/* Adesso pa vale 1008 !!!!!!!!! */

Questa è una delle proprietà fondamentali nell'aritmetica dei puntatori. Tutti i calcoli aritmetici che si possono fare sui puntatori presuppongono che l'unità base non sia 1 (1 byte) ma la dimensione del dato puntato.

Altro esempio:
double arr[6] = { 4, 2, 5, 7, 1, 9 }; /* l'array parte da 1000 (es.) */
+---+
| 4 | 1000
+---+
| 2 | 1008
+---+
| 5 | 1016
+---+
| 7 | 1024
+---+
| 1 | 1032
+---+
| 9 | 1040
+---+double *pa = arr; /* Non serve la &, arr è già un indirizzo! */

pa = pa + 2 * 2;

Non vuol dire che adesso pa vale 1000+4, cioè 1004!!!!!
pa vale 1032 (punta alla cella con valore 1) perché ci si è spostati alla 5a cella. In pratica il puntatore è avanzato di 4 celle, non di 4 byte nello spazio di indirizzamento!!

Spero di averti chiarito questa cosa!

vermaccio
28-03-2006, 16:20
e come faccio a sapere ogni cella quanti bits sono? effettivamente , però, è un dato che non serve. se ho ben capito mi serve ragionare solo in termini di blocchi di bits di cui avanzo., sapere ogni blocco quanti bits sono non serve. basta sapere il numero di blocchi.
esatto?

per avanzare di 3 elementi nella matrice io avanzo di 3 blocchi con i puntatori. poi che ogni blocco sia 8 bits o altro lo fa da solo il compilatore. è così?

andbin
28-03-2006, 16:29
Per vermaccio: se non sei ancora convinto, prova questo codice:
#include <stdio.h>

int main (void)
{
double arr[6] = { 4, 2, 6, 7, 3, 1 };

printf ("%f\n", arr[3]);
printf ("%f\n", *(arr+3));

printf ("%u\n", arr);
printf ("%u\n", &arr[3]);
printf ("%u\n", arr+3);

return 0;
}
Le prime due printf stampano lo stesso valore, cioè il valore della 4a cella (quella con indice 3) e quindi con valore 7.
Le successive tre printf stampano l'indirizzo di arr e l'indirizzo (2 volte) della 4a cella.

Esempio di output:
7.000000
7.000000
2147481432
2147481456
2147481456

Nota che arr, da solo, è un indirizzo.
C'è una correlazione molto forte tra array e puntatori. Ed è per questo che dato un array arr, è vero che arr[i] è uguale a *(arr+i).

vermaccio
28-03-2006, 16:29
e comunque, se ho ben capito, allora
dire A[i][j] è quindi equivalente a dire
*(pa + i*j + j)
e non
*(pa + i*3 + j).
(notare il j al posto del 3)

andbin
28-03-2006, 16:36
e comunque, se ho ben capito, allora
dire A[i][j] è quindi equivalente a dire
*(pa + i*j + j)
e non
*(pa + i*3 + j).
(notare il j al posto del 3)
No, i e j sono gli indici. Quello che dovresti mettere al posto del 3 è il numero delle colonne!!! Quindi dipende da come è fatto l'array bidimensionale.

Esempio:
double a[4][3] = ...;
double *pa = &a[0][0];

a[i][j] è uguale a *(pa + i*3 + j)

ma

double b[6][8] = ...;
double *pb = &b[0][0];

b[i][j] è uguale a *(pb + i*8 + j)

P.S.: Leggi anche il mio post precedente.

vermaccio
28-03-2006, 16:43
uff...
finalmente mi si sono chiarite molte cose.
ora proverò ad implementare.
comunuqe ti ringrazio della tua infinita gentilezza e pazienza.

ciao

andbin
28-03-2006, 16:48
e come faccio a sapere ogni cella quanti bits sono? effettivamente , però, è un dato che non serve. se ho ben capito mi serve ragionare solo in termini di blocchi di bits di cui avanzo., sapere ogni blocco quanti bits sono non serve. basta sapere il numero di blocchi.
esatto?

per avanzare di 3 elementi nella matrice io avanzo di 3 blocchi con i puntatori. poi che ogni blocco sia 8 bits o altro lo fa da solo il compilatore. è così?
Esatto.
Comunque se uno volesse sapere la dimensione (e questo vale in generale) di una variabile basta usare l'operatore sizeof.
Quindi ad esempio sizeof(double) oppure sizeof(*ptr) se si ha un puntatore.

andbin
28-03-2006, 16:51
uff...
finalmente mi si sono chiarite molte cose.
Meno male ... l'importante è che adesso tu abbia capito i puntatori. :)
Adesso è ora di andare a casa ... a forza di spiegarti i puntatori non so se sei più fuso tu oppure io. :p

vermaccio
28-03-2006, 17:29
#include<stdio.h>
#include <math.h>

double A[2][2]= { {1, 2},{3,4} };
double B[2][2]= { {5,6},{7,-8} };
double C[4][3]= { {1, -2, 3},{-5, 0, 7},{-2, -1, 5},{3, 0, -1} };
double D[3][4]= { {1, 2, 3, 4},{5, 6, 7, 8},{-2, 1, -5, 12} };



double AB[2][2];
double CD[4][4];



//XXXXXXXXXXXXXXXXXXXXXXXX
//funzione prodotto di due matrici
//XXXXXXXXXXXXXXXXXXXXXXXXX

void prodottomatrici(double *matrA, int nrigA, int ncolA, double *matrB, int nrigB, int ncolB, double *matrC, int nrigC, int ncolC) {

//i=righeA
//j=colonneB
//k=colonneA=righeB !!!!!!! se colonneA diverso da righeB si ha errore

double i, j, k; //variabili locali
double elemA, elemB, elemC; //variabili locali

for (i=0; i<nrigA; i++){ //scorro riga di matrice risultato
for (j=0; j<ncolB; j++){ //scorro colonna di matrice risultato
elemC=0; // sarebbe la matC[i][j]=0;
for (k=0; k<ncolA; k++){ //oppure k<nrigB visto che ncolA=nrigB
elemA = *(matrA + i * ncolA + k); //sarebbe la matA[i][k]
elemB = *(matrB + k * ncolB + j); //sarebbe la matB[k][j]

elemC = elemC+elemA*elemB; //sarebbe la matC[i][j]=matC[i][j]+matA[i][k]*matB[k][j];
//test=A[i][k]*B[k][j];
//printf("%g\n", test );
}
*(matrC + i * ncolC + j) = elemC;//ora assegno il risultato "elemC" alla matrice di uscita assegnando al puntatore
//adatto relativo alla giusta cella della matrice quel valore "elemC"

//printf("%g\n", matC[i][j] );
}
}


}








//--------------------
void main(void)
{

//notare gli [0][0] perchè sto passando i puntatori alprimo elemento della matrice
prodottomatrici (&A[0][0], 2, 2, &B[0][0], 2, 2, &AB[0][0], 2, 2);
printf("elemento [1][2] matrice prodotto A*B: %g\n", AB[0][1] );

//notare gli [0][0] perchè sto passando i puntatori alprimo elemento della matrice
prodottomatrici (&C[0][0], 4, 3, &D[0][0], 3, 4, &CD[0][0], 2, 2);
printf("elemento [1][2] matrice prodotto C*D: %g\n", CD[0][1] );

}




compilando ho vari errori
error C2111: '+' : pointer addition requires integral operand

riferiti alle istruzioni
elemA = *(matrA + i * ncolA + k);

elemB = *(matrB + k * ncolB + j);

elemC = elemC+elemA*elemB;

vermaccio
28-03-2006, 18:10
invece questo che fa solo la somma di due elementi di due mtatrici funziona.
ma che cambia tra un programma e l'altro da dare quell'errore?

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

double A[2][2]= { {1, 2},{3,4} };
double B[2][2]= { {5,6},{7,-8} };
double C[4][3]= { {1, -2, 3},{-5, 0, 7},{-2, -1, 5},{3, 0, -1} };
double D[3][4]= { {1, 2, 3, 4},{5, 6, 7, 8},{-2, 1, -5, 12} };



double AB[2][2];
double CD[4][4];




void prodottofunzioni (double *matrA, int nrigA, int ncolA, double *matrB, int nrigB, int ncolB, double *matrC, int nrigC, int ncolC)
{
int iA, jA;
int iB, jB;
int iC, jC;
double elemA, elemB, elemC;


//somma elementi [1][2] di matrici (ovvero in array [0][1])in input e metto il risultato in matrice di output

iA=0;//posizione elemento matrice A
jA=1;

iB=0;//posizione elemento matrice B
jB=1;

iC=0;//posizione elemento matrice C dove mettere il risultato
jC=1;


//prendo gli elementi di matrici usando i puntatori
elemA = *(matrA + iA * ncolA + jA);
elemB = *(matrB + iB * ncolB + jB);

//effettuo il calcolo
elemC = elemA+elemB;

//ora assegno il risultato "elemC" alla matrice di uscita assegnando al puntatore
//adatto relativo alla giusta cella della matrice quel valore "elemC"
*(matrC + iC * ncolC + jC) = elemC;

}








//--------------------
void main(void)
{

//notare gli [0][0] perchè sto passando i puntatori alprimo elemento della matrice
prodottofunzioni (&A[0][0], 2, 2, &B[0][0], 2, 2, &AB[0][0], 2, 2);
printf("somma elementi matrici [1][2]: %g\n", AB[0][1] );

//notare gli [0][0] perchè sto passando i puntatori alprimo elemento della matrice
prodottofunzioni (&C[0][0], 4, 3, &D[0][0], 3, 4, &CD[0][0], 2, 2);
printf("somma elementi matrici [1][2]: %g\n", CD[0][1] );

}

vermaccio
28-03-2006, 18:16
scrivendo
int i, j, k; //variabili locali
invece di
double i, j, k; //variabili locali
funziona.

però perchè non ha dato quell'errore anche nel secondo?????????

andbin
28-03-2006, 18:23
compilando ho vari errori
error C2111: '+' : pointer addition requires integral operand
Come ti dice bene il compilatore, le variabili i, j e k devono essere intere e non double. Quindi:
int i, j, k; //variabili locali

Io ho provato a compilare il sorgente su Linux e mi da (giustamente) l'errore sulle righe 32, 33 e 39. Il tipo e il modo di segnalazione degli errori dipende ovviamente dal compilatore!

vermaccio
28-03-2006, 18:26
ecco finalmente il listato testato e funzionante


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

double A[2][2]= { {1, 2},{3,4} };
double B[2][2]= { {5,6},{7,-8} };
double C[4][3]= { {1, -2, 3},{-5, 0, 7},{-2, -1, 5},{3, 0, -1} };
double D[3][4]= { {1, 2, 3, 4},{5, 6, 7, 8},{-2, 1, -5, 12} };



double AB[2][2];
double CD[4][4];



//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//funzione prodotto di due matrici 4X4 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

void prodottomatrici(double *matrA, int nrigA, int ncolA, double *matrB, int nrigB, int ncolB, double *matrC, int nrigC, int ncolC) {

//i=righeA
//j=colonneB
//k=colonneA=righeB !!!!!!! se colonneA diverso da righeB si ha errore

int i, j, k; //variabili locali
double elemA, elemB, elemC; //variabili locali

for (i=0; i<nrigA; i++){ //scorro riga di matrice risultato
for (j=0; j<ncolB; j++){ //scorro colonna di matrice risultato
elemC=0; // sarebbe la matC[i][j]=0;
for (k=0; k<ncolA; k++){ //oppure k<nrigB visto che ncolA=nrigB
elemA = *(matrA + i * ncolA + k); //sarebbe la matA[i][k]
elemB = *(matrB + k * ncolB + j); //sarebbe la matB[k][j]

elemC = elemC+elemA*elemB; //sarebbe la matC[i][j]=matC[i][j]+matA[i][k]*matB[k][j];
//test=A[i][k]*B[k][j];
//printf("%g\n", test );
}
*(matrC + i * ncolC + j) = elemC;//ora assegno il risultato "elemC" alla matrice di uscita assegnando al puntatore
//adatto relativo alla giusta cella della matrice quel valore "elemC"

//printf("%g\n", matC[i][j] );
}


}


}








//--------------------
void main(void)
{

//notare gli [0][0] perchè sto passando i puntatori alprimo elemento della matrice
prodottomatrici (&A[0][0], 2, 2, &B[0][0], 2, 2, &AB[0][0], 2, 2);
printf("elemento [1][1] matrice prodotto A*B: %g\n", AB[0][0] );
printf("elemento [1][2] matrice prodotto A*B: %g\n", AB[0][1] );
printf("elemento [2][1] matrice prodotto A*B: %g\n", AB[1][0] );
printf("elemento [2][2] matrice prodotto A*B: %g\n", AB[1][1] );


printf("-------------------------- \n");


//notare gli [0][0] perchè sto passando i puntatori alprimo elemento della matrice
prodottomatrici (&C[0][0], 4, 3, &D[0][0], 3, 4, &CD[0][0], 4, 4);
printf("elemento [1][1] matrice prodotto C*D: %g\n", CD[0][0] );
printf("elemento [1][2] matrice prodotto C*D: %g\n", CD[0][1] );
printf("elemento [1][3] matrice prodotto C*D: %g\n", CD[0][2] );
printf("elemento [1][4] matrice prodotto C*D: %g\n", CD[0][3] );

printf("elemento [2][1] matrice prodotto C*D: %g\n", CD[1][0] );
printf("elemento [2][2] matrice prodotto C*D: %g\n", CD[1][1] );
printf("elemento [2][3] matrice prodotto C*D: %g\n", CD[1][2] );
printf("elemento [2][4] matrice prodotto C*D: %g\n", CD[1][3] );

printf("elemento [3][1] matrice prodotto C*D: %g\n", CD[2][0] );
printf("elemento [3][2] matrice prodotto C*D: %g\n", CD[2][1] );
printf("elemento [3][3] matrice prodotto C*D: %g\n", CD[2][2] );
printf("elemento [3][4] matrice prodotto C*D: %g\n", CD[2][3] );

printf("elemento [4][1] matrice prodotto C*D: %g\n", CD[3][0] );
printf("elemento [4][2] matrice prodotto C*D: %g\n", CD[3][1] );
printf("elemento [4][3] matrice prodotto C*D: %g\n", CD[3][2] );
printf("elemento [4][4] matrice prodotto C*D: %g\n", CD[3][3] );

}



/*risultati matlab
AB =
19 -10
43 -14
risultato c++: OK

CD =
-15 -7 -26 24
-19 -3 -50 64
-17 -5 -38 44
5 5 14 0
risultato c++: OK
*/



grazie di tutto!!!!!!!!!

comunque ancora non capisco perchè con double al posto di int il secondo programma funzionava ed il primo no.


ora che il proghramma funziona......

la DOMANDA.

tu come avresti fatto?

avresti usato gliarray con questo incubo di puntatori oppure...

cosa?

andbin
28-03-2006, 18:31
comunque ancora non capisco perchè con double al posto di int il secondo programma funzionava ed il primo no.Perché avevi usato gli int per gli indici, se guardi bene!

tu come avresti fatto?

avresti usato gliarray con questo incubo di puntatori oppure...

cosa?Credo che anche io avrei fatto così ...

vermaccio
28-03-2006, 19:46
ti ho consegnato all'immortalità

http://www.hwupgrade.it/forum/showthread.php?p=11810646#post11810646


:)

andbin
28-03-2006, 20:21
Ciao, ho provato anche io ad implementare il programma per il calcolo del prodotto di 2 matrici.

Ecco la mia personalissima soluzione:
#include <stdio.h>
#include <stdlib.h>

typedef struct
{
double *array;
int rows;
int columns;
} MATRIX_2D, *PMATRIX_2D;


/******************************************************************************/
/* FUNZIONI GENERICHE DI GESTIONE MATRICI */
/******************************************************************************/
double Matrix2D_GetValue (PMATRIX_2D pmatrix, int r, int c)
{
return *(pmatrix->array + r * pmatrix->columns + c);
}

void Matrix2D_SetValue (PMATRIX_2D pmatrix, int r, int c, double value)
{
*(pmatrix->array + r * pmatrix->columns + c) = value;
}

void Matrix2D_AddValue (PMATRIX_2D pmatrix, int r, int c, double value)
{
*(pmatrix->array + r * pmatrix->columns + c) += value;
}

int Matrix2D_Product (PMATRIX_2D pmatrix_a, PMATRIX_2D pmatrix_b, PMATRIX_2D pmatrix_out)
{
int rows, columns, r, c, i;

if (pmatrix_a->columns != pmatrix_b->rows)
return 0; /* Errore, matrici non compatibili! */

rows = pmatrix_a->rows;
columns = pmatrix_b->columns;

/* Allocazione matrice del prodotto */
pmatrix_out->array = (double*) malloc (rows * columns * sizeof (double));
pmatrix_out->rows = rows;
pmatrix_out->columns = columns;

for (r = 0; r < rows; r++)
{
for (c = 0; c < columns; c++)
{
Matrix2D_SetValue (pmatrix_out, r, c, 0.0);

for (i = 0; i < pmatrix_a->columns; i++)
{
Matrix2D_AddValue (pmatrix_out, r, c,
Matrix2D_GetValue (pmatrix_a, r, i) *
Matrix2D_GetValue (pmatrix_b, i, c));
}
}
}

return 1; /* Successo */
}

void Matrix2D_Free (PMATRIX_2D pmatrix)
{
free (pmatrix->array);
}

void Matrix2D_Print (PMATRIX_2D pmatrix)
{
int r, c;

for (r = 0; r < pmatrix->rows; r++)
{
for (c = 0; c < pmatrix->columns; c++)
{
if (c > 0)
printf (" ");

printf ("%9.3f", Matrix2D_GetValue (pmatrix, r, c));
}

printf ("\n");
}
}


/******************************************************************************/
/* MAIN */
/******************************************************************************/
double a[4][3]= { {1, -2, 3}, {-5, 0, 7}, {-2, -1, 5}, {3, 0, -1} };
double b[3][4]= { {1, 2, 3, 4}, {5, 6, 7, 8}, {-2, 1, -5, 12} };


int main (void)
{
MATRIX_2D matrix_a = { &a[0][0], 4, 3 };
MATRIX_2D matrix_b = { &b[0][0], 3, 4 };

MATRIX_2D matrix_prod;

if (Matrix2D_Product (&matrix_a, &matrix_b, &matrix_prod) != 0)
{
printf ("Matrice A\n");
Matrix2D_Print (&matrix_a);

printf ("\n");
printf ("Matrice B\n");
Matrix2D_Print (&matrix_b);

printf ("\n");
printf ("Matrice Prodotto\n");
Matrix2D_Print (&matrix_prod);

Matrix2D_Free (&matrix_prod);
}

return 0;
}

Il programma in output mi fornisce:
Matrice A
1.000 -2.000 3.000
-5.000 0.000 7.000
-2.000 -1.000 5.000
3.000 0.000 -1.000

Matrice B
1.000 2.000 3.000 4.000
5.000 6.000 7.000 8.000
-2.000 1.000 -5.000 12.000

Matrice Prodotto
-15.000 -7.000 -26.000 24.000
-19.000 -3.000 -50.000 64.000
-17.000 -5.000 -38.000 44.000
5.000 5.000 14.000 0.000

vermaccio
28-03-2006, 20:50
dagli in ingresso:

double A[2][2]= { {1, 2},{3,4} };
double B[2][2]= { {5,6},{7,-8} };
double C[4][3]= { {1, -2, 3},{-5, 0, 7},{-2, -1, 5},{3, 0, -1} };
double D[3][4]= { {1, 2, 3, 4},{5, 6, 7, 8},{-2, 1, -5, 12} };




risultati esatti calcolati con matlab che devi ottenere

A*B =
19 -10
43 -14


C*D =
-15 -7 -26 24
-19 -3 -50 64
-17 -5 -38 44
5 5 14 0

andbin
28-03-2006, 21:13
dagli in ingresso:

double C[4][3]= { {1, -2, 3},{-5, 0, 7},{-2, -1, 5},{3, 0, -1} };
double D[3][4]= { {1, 2, 3, 4},{5, 6, 7, 8},{-2, 1, -5, 12} };

risultati esatti calcolati con matlab che devi ottenere

C*D =
-15 -7 -26 24
-19 -3 -50 64
-17 -5 -38 44
5 5 14 0
:doh: Cavoli ... ecco cosa ho dimenticato di fare: la sommatoria dei valori!!!!
A quest'ora della sera secondo te quanto sono fuso da 1 a 10??? :p

Comunque ho aggiornato il post #36 (capperi quanto abbiamo scritto!) con il nuovo codice e il nuovo output, che adesso è come hai appena riportato tu.
Ho aggiunto la funzione Matrix2D_AddValue (per fare facilmente la sommatoria). Adesso imposto prima a 0 il valore della cella e poi man mano effettuo la sommatoria dei valori.

Cosa ne pensi della mia soluzione?? È una soluzione un po' più complessa ma molto più "astratta" dal punto di vista della gestione delle matrici.
Io ho sempre una "visione" molto object-like quando programmo e cerco sempre di incapsulare/separare/strutturare il codice il più possibile!

Grazie mille, naturalmente!!!

andbin
28-03-2006, 21:24
... e grazie al tuo thread ho anche imparato a fare il prodotto di 2 matrici! :)

vermaccio
29-03-2006, 08:44
hehehe. anche io cerco di creare sottofinzuoni separate. ecco perchè ho scritto questo programmino per fare il prodotto di due matrici!

comunque:
ora sarebbe da soffrire e fare una funzione per il calcolo del determinante di due matrici.

ho un listato (non mio) che contiene una 4 o 5 funzioni che permette di calcolarlo ma solo per matrici 4X4. il determinante si può calcolare solo per matrici quadrate. ma solo 4X4 è limitante. calcolarlo per una 5X5 sono dolori.
magari inizio a scrivere l'agoritmo base poi vediamo come implementarlo!

andbin
29-03-2006, 09:11
ora sarebbe da soffrire e fare una funzione per il calcolo del determinante di due matrici.Mi sono appena documentato un po' tramite Wikipedia, come al solito.
Il determinante di una matrice è bello tosto!!! (E io sono molto arruginito in matematica!) :D

vermaccio
29-03-2006, 10:01
esiste un metodo che prende la matrice, la scompone in sottomatrici sino ad avere matrici 2X2 e poi calcola un mare di determinanti e infine li compone per avere il det della matrice principale.

se vuoi ti metto qui in allegato il documento che ho in cui si fa il drt di matrici 2X2 8una cavolata), 3X3 e 4X4. il dilemma è: e 5X5 e 6X6 che mi capitano a me??????