Proizvod matrice (C jezik)

Zar nije torta hladna

Aktivan član
Poruka
1.205
Treba da uradim zadatak koji će da računa sumu,razliku i proizvod dve matrice ali da nam operacije budu potprogrami. E sad mene zeza proizvod bukvlano ne kapiram gde sam pogrešio.

Evo mog pokušaja

C:
#include<stdio.h>

int suma(int a[100][100],int b[100][100],int c[100][100], int red,int kolona)
{
    int i,j;

    for(i=1; i<=red; i++)
     for(j=1; j<=kolona; j++)
      c[i][j] =  (a[i][j] + b[i][j]);

    return c[i][j];
}

int razlika(int a[100][100],int b[100][100],int c[100][100], int red,int kolona)
{
    int i,j;

    for(i=1; i<=red; i++)
     for(j=1; j<=kolona; j++)
      c[i][j] =  (a[i][j] - b[i][j]);

    return c[i][j];
}

int proizvod(int a[100][100],int b[100][100],int c[100][100], int red,int kolona)

{
    int i, j, k;

    for(i = 0; i < red; ++i)
    {
        for(j = 0; j < kolona; ++j)
        {
            c[i][j] = 0;
        }
    }

    for(i = 0; i < red; ++i)
    {
        for(j = 0; j < kolona; ++j)
        {
            for(k=0; k<kolona; ++k)
            {
                c[i][j] += a[i][k] * b[k][j];
            }
        }
    }

  return c[i][j];

}

int main()
{
    int a[100][100],b[100][100],s[100][100],r[100][100],p[100][100],red,kolona,i,j;

    printf("Unesi broj redova:");
    scanf("%d",&red);

    printf("Unesi broj kolona:");
    scanf("%d",&kolona);

    printf("\n");
    
    printf("Unesi elemente matrice A:\n");

    for(i=1;i<=red;i++)
    {
    for(j=1;j<=kolona;j++)
    {
        printf("a%d%d : ",i,j);
        scanf("%d",&a[i][j]);
            }
    }
    
    printf("\n");

    printf("Unesi elemente matrice B:\n");

    for(i=1;i<=red;i++)
    {
    for(j=1;j<=kolona;j++)
    {
        printf("b%d%d : ",i,j);
        scanf("%d",&b[i][j]);
            }
    }

    printf("\n");

    suma(a,b,s,red,kolona);

    for(i=1;i<=red;i++)
    {
     for(j=1;j<=kolona;j++)
     {
      printf("%d ",s[i][j]);
     }
    printf("\n\n");
    }
    
    printf("\n");

    razlika(a,b,r,red,kolona);

    for(i=1;i<=red;i++)
    {
     for(j=1;j<=kolona;j++)
     {
      printf("%d ",r[i][j]);
     }
    printf("\n");
    }

    printf("\n");

    proizvod(a,b,p,red,kolona);

    for(i=1;i<=red;i++)
    {
     for(j=1;j<=kolona;j++)
     {
      printf("%d ",p[i][j]);
     }
    printf("\n");
    }

    return 0;
}
 
Evo primer kako mi radi program.

Screenshot_1.png
 
Jel se zezaš ili ozbiljno?
Nulu kod množenja dobijaš samo ako je neki element matrice jednak nuli.
Negativan broj samo ako je rezultat veći od maxint.

Gledam na brzinu, ali zašto upotrebljavaš kolone 2 puta za množenje i dodaješ na postojeću vrednost?

Probaj neki debug ispis u stilu: kolona_x(vrednost) * red_y(vrednost) = rezultat_z, pa vidi dalje...
 
није баш у цеу али преведи из бејзика.. ради проверено:

Public Type MatrixType
d(1 To 19, 1 To 19) As Double 'matrix data
x As Integer 'matrix size
y As Integer
End Type

Public Function MatrixMul(a As MatrixType, b As MatrixType) As MatrixType
'mnozi dve matrice, gde je prva veca a druga manja
Dim o As MatrixType
Dim i, k As Integer
If a.x = b.y Then
For k = 1 To b.y
o.d(1, k) = 0
For i = 1 To a.x
o.d(1, k) = o.d(1, k) + a.d(i, k) * b.d(1, i)
Next i
Next k
Else
MsgBox "matrix size mismatch for multiplication"
End If
o.x = b.x
o.y = b.y
MatrixMul = o
End Function
 
Зашто си обрнуо инкременте? Некад ти матрице иду [0, i) a некад од [1, i].
Пробај са:

Kod:
#include<stdio.h>


int proizvod(int a[100][100],int b[100][100],int c[100][100], int red,int kolona)

{
    int i, j, k;

    for(i = 1; i <= red; i++)
    {
        for(j = 1; j <= kolona; j++)
        {
            c[i][j] = 0;
        }
    }

 for(i = 1; i <= red; i++)
    {
        for(j = 1; j <= kolona; j++)
        {
            for(k=1; k <= kolona; k++)
            {
               printf("a%d%d%d : %d",i,k,j, a[i][k] * b[k][j]);
                printf("\n");
                c[i][j] += a[i][k] * b[k][j];
            }
        }
    }

  return c[i][j];

}

int main()
{
    int a[100][100],b[100][100],c[100][100],red,kolona,i,j;

    printf("Unesi broj redova:");
    scanf("%d",&red);

    printf("Unesi broj kolona:");
    scanf("%d",&kolona);

    printf("\n");
 
    printf("Unesi elemente matrice A:\n");

    for(i=1;i<=red;i++)
    {
    for(j=1;j<=kolona;j++)
    {
        printf("a%d%d : ",i,j);
        scanf("%d",&a[i][j]);
            }
    }
 
    printf("\n");

    printf("Unesi elemente matrice B:\n");

    for(i=1;i<=red;i++)
    {
    for(j=1;j<=kolona;j++)
    {
        printf("b%d%d : ",i,j);
        scanf("%d",&b[i][j]);
            }
    }

    printf("\n");

 
    printf("\n");
    proizvod(a,b,c,red,kolona);
    printf("\n");

    for(i=1;i<=red;i++)
    {
     for(j=1;j<=kolona;j++)
     {
      printf("%d ",c[i][j]);
     }
    printf("\n");
    }

    return 0;
}
 
Poslednja izmena:
Ovo je kod samo za proizvodom, sada cu ti ispricati sta kod tebe ne valja

#include<stdio.h>
#include<stdlib.h>
int** proizvod(int**, int, int, int**, int, int);
void ispis(int**, int, int);
void obrisi(int**, int);
int main() {
//2 matrice koje cemo koristiti i njihove velicine
int** mat1 = NULL;
int** mat2 = NULL;
int n1 = 2;
int m1 = 3;
int n2 = 3;
int m2 = 2;
//alociram matricu 1
mat1 = (int**)calloc(n1,sizeof(int*));
for (int i = 0; i < n1; i++) {
mat1 = (int*)calloc(m1, sizeof(int));
}
//upisem neke vrednosti
mat1[0][0] = 1; mat1[0][1] = 2; mat1[0][2] = 3;
mat1[1][0] = 4; mat1[1][1] = 5; mat1[1][2] = 6;
//ispisem
ispis(mat1, n1, m1);
//alociram matricu 2
mat2 = (int**)calloc(n2, sizeof(int*));
for (int i = 0; i < n2; i++) {
mat2 = (int*)calloc(m2, sizeof(int));
}
//upisem neke vrednosti
mat2[0][0] = 7; mat2[0][1] = 8;
mat2[1][0] = 9; mat2[1][1] = 10;
mat2[2][0] = 11; mat2[2][1] = 12;
//ispisem
ispis(mat2, n2, m2);
//matrica 3 ce biti proizvod ovih 2, saljem matrice i velicinu
int** mat3 = proizvod(mat1,n1,m1, mat2, n2, m2);
//vrste iz prve a kolone iz druge
//ispisem
ispis(mat3, n1, m2);
obrisi(mat1, n1);
obrisi(mat2, n2);
obrisi(mat3, n1);
return 0;
}
//ispisem matricu
void ispis(int** mat,int n,int m) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
printf("%d ", mat[j]);
}
putchar('\n');
}
putchar('\n');
}
/*
* Racuanje proizvoda matrice na sledeci nacin
* Alociram matricu velicine n1xm2 jer to je velicina pomnozene matrice
* onda idemo kroz tu matricu i dodajemo na vrednost polja proizvod
* prve i druge matrice, na kraju vratimo matricu
*/
int** proizvod(int** mat1, int n1, int m1, int** mat2,int n2,int m2) {
//alociranje matrice
int** mat = (int**)calloc(n1, sizeof(int*));
for (int i = 0; i < n1; i++) {
mat = (int*)calloc(m2, sizeof(int));
}
//petlja koja ce proci kroz celu matricu
for (int i = 0; i < n1; i++) {
for (int j = 0; j < m2; j++) {
//za svako polje idemo kroz kolone prve i vrste druge
for (int k = 0; k < n2; k++) {
//na matricu dodajemo proizvod ta 2 broja
mat[j] += mat1[k] * mat2[k][j];
}
}
}
//vratimo matricu
return mat;
}

void obrisi(int** mat, int n) {
for (int i = 0; i < n; i++) {
free(mat);
}
free(mat);
}
 
Treba da uradim zadatak koji će da računa sumu,razliku i proizvod dve matrice ali da nam operacije budu potprogrami. E sad mene zeza proizvod bukvlano ne kapiram gde sam pogrešio.

Evo mog pokušaja

C:
#include<stdio.h>

int suma(int a[100][100],int b[100][100],int c[100][100], int red,int kolona)
{
    int i,j;

    for(i=1; i<=red; i++)
     for(j=1; j<=kolona; j++)
      c[i][j] =  (a[i][j] + b[i][j]);

    return c[i][j];
}

int razlika(int a[100][100],int b[100][100],int c[100][100], int red,int kolona)
{
    int i,j;

    for(i=1; i<=red; i++)
     for(j=1; j<=kolona; j++)
      c[i][j] =  (a[i][j] - b[i][j]);

    return c[i][j];
}

int proizvod(int a[100][100],int b[100][100],int c[100][100], int red,int kolona)

{
    int i, j, k;

    for(i = 0; i < red; ++i)
    {
        for(j = 0; j < kolona; ++j)
        {
            c[i][j] = 0;
        }
    }

    for(i = 0; i < red; ++i)
    {
        for(j = 0; j < kolona; ++j)
        {
            for(k=0; k<kolona; ++k)
            {
                c[i][j] += a[i][k] * b[k][j];
            }
        }
    }

  return c[i][j];

}

int main()
{
    int a[100][100],b[100][100],s[100][100],r[100][100],p[100][100],red,kolona,i,j;

    printf("Unesi broj redova:");
    scanf("%d",&red);

    printf("Unesi broj kolona:");
    scanf("%d",&kolona);

    printf("\n");
   
    printf("Unesi elemente matrice A:\n");

    for(i=1;i<=red;i++)
    {
    for(j=1;j<=kolona;j++)
    {
        printf("a%d%d : ",i,j);
        scanf("%d",&a[i][j]);
            }
    }
   
    printf("\n");

    printf("Unesi elemente matrice B:\n");

    for(i=1;i<=red;i++)
    {
    for(j=1;j<=kolona;j++)
    {
        printf("b%d%d : ",i,j);
        scanf("%d",&b[i][j]);
            }
    }

    printf("\n");

    suma(a,b,s,red,kolona);

    for(i=1;i<=red;i++)
    {
     for(j=1;j<=kolona;j++)
     {
      printf("%d ",s[i][j]);
     }
    printf("\n\n");
    }
   
    printf("\n");

    razlika(a,b,r,red,kolona);

    for(i=1;i<=red;i++)
    {
     for(j=1;j<=kolona;j++)
     {
      printf("%d ",r[i][j]);
     }
    printf("\n");
    }

    printf("\n");

    proizvod(a,b,p,red,kolona);

    for(i=1;i<=red;i++)
    {
     for(j=1;j<=kolona;j++)
     {
      printf("%d ",p[i][j]);
     }
    printf("\n");
    }

    return 0;
}
Okej, prvo, ne valja ti indeksiranje, indeksiras od 1, to se ne radi u C, no nema veze ako si konstantna a ti nisi. U funkciji adresiras od 0, a unosio si od 1. Prvo to.
Druga stvar, matrice se ne mogu pomnizi osim ako nisu ovakve
matrica1 - NxM
matrica2 - MxN

tebi to nije slucaj, imas 2 iste matrice, njih ne mozes mnoziti
 
Izvoli tvoj kod izmenjen da radi, napisao sam komentarom modifikacija

C:
#include<stdio.h>

int suma(int a[100][100], int b[100][100], int c[100][100], int red, int kolona)
{
    int i, j;

    for (i = 1; i <= red; i++)
        for (j = 1; j <= kolona; j++)
            c[i][j] = (a[i][j] + b[i][j]);

    return c[i][j];
}

int razlika(int a[100][100], int b[100][100], int c[100][100], int red, int kolona)
{
    int i, j;

    for (i = 1; i <= red; i++)
        for (j = 1; j <= kolona; j++)
            c[i][j] = (a[i][j] - b[i][j]);

    return c[i][j];
}
//salju se obicno argumenti ovako, jer je nebitna duzina svega do poslednjeg
int proizvod(int a[][100], int b[][100], int c[][100], int red, int kolona)
{
    int i, j, k;
    //indeksirao si od 0, a trebas od 1, msm treba od 0 ali si ceo program od 1
    //pa moras i ovde, inace imas junk vrednosti
    //mada vise ti nije potrebno ovo jer sam je inicijalizovao sa 0
    for (i = 1; i <= red; ++i)
    {
        for (j = 1; j <= red; ++j)
        {
            c[i][j] = 0;
        }
    }
    //ponovo od 1 sam indeksirao i promenio, ta nova matrica treba biti
    //REDxRED a ne REDxKOLONA ali gledas po kolonama u ovaj treci for
    for (i = 1; i <= red; ++i)
    {
        for (j = 1; j <= red; ++j)
        {
            for (k = 1; k <= kolona; ++k)
            {
                c[i][j] += a[i][k] * b[k][j];
            }
        }
    }
    //ne kapiram zasto vracas bilo sta...??
    return c[i][j];
}

int main()
{
    // p[100][100] = { 0 }, znaci da su sve 0
    int a[100][100], b[100][100], s[100][100], r[100][100], p[100][100] = { 0 }, red, kolona, i, j;

    printf("Unesi broj redova:");
    scanf("%d", &red);

    printf("Unesi broj kolona:");
    scanf("%d", &kolona);

    printf("\n");

    printf("Unesi elemente matrice A:\n");

    for (i = 1; i <= red; i++)
    {
        for (j = 1; j <= kolona; j++)
        {
            printf("a%d%d : ", i, j);
            scanf("%d", &a[i][j]);
        }
    }

    printf("\n");

    printf("Unesi elemente matrice B:\n");

    for (i = 1; i <= red; i++)
    {
        for (j = 1; j <= kolona; j++)
        {
            printf("b%d%d : ", i, j);
            scanf("%d", &b[i][j]);
        }
    }

    printf("\n");

    suma(a, b, s, red, kolona);
    printf("s\n");
    for (i = 1; i <= red; i++)
    {
        for (j = 1; j <= kolona; j++)
        {
            printf("%d ", s[i][j]);
        }
        printf("\n\n");
    }

    printf("\n");

    razlika(a, b, r, red, kolona);
    printf("r\n");
    for (i = 1; i <= red; i++)
    {
        for (j = 1; j <= kolona; j++)
        {
            printf("%d ", r[i][j]);
        }
        printf("\n");
    }
    printf("\n");
    //transponujem B
    int transB[100][100] = { 0 };
    for (int i = 1; i <= kolona; i++) {
        for (int j = 1; j <= red; j++) {
            transB[i][j] = b[j][i];
        }
    }
    proizvod(a, transB, p, red, kolona);
    //pomnozena matrica je REDxRED a ne REDxKOLONA
    for (i = 1; i <= red; i++)
    {
        for (j = 1; j <= red; j++)
        {
            printf("%d ", p[i][j]);
        }
        printf("\n");
    }

    return 0;
}
 
Evo i mog, malo je bolje ovako pisati, isto formatiran

C:
#include<stdio.h>
#include<stdlib.h>
int** proizvod(int**, int, int, int**, int, int);
void ispis(int**, int, int);
void obrisi(int**, int);
int main() {
//2 matrice koje cemo koristiti i njihove velicine
int** mat1 = NULL;
int** mat2 = NULL;
int n1 = 2;
int m1 = 3;
int n2 = 3;
int m2 = 2;
//alociram matricu 1
mat1 = (int**)calloc(n1,sizeof(int*));
for (int i = 0; i < n1; i++) {
mat1 = (int*)calloc(m1, sizeof(int));
}
//upisem neke vrednosti
mat1[0][0] = 1; mat1[0][1] = 2; mat1[0][2] = 3;
mat1[1][0] = 4; mat1[1][1] = 5; mat1[1][2] = 6;
//ispisem
ispis(mat1, n1, m1);
//alociram matricu 2
mat2 = (int**)calloc(n2, sizeof(int*));
for (int i = 0; i < n2; i++) {
mat2 = (int*)calloc(m2, sizeof(int));
}
//upisem neke vrednosti
mat2[0][0] = 7; mat2[0][1] = 8;
mat2[1][0] = 9; mat2[1][1] = 10;
mat2[2][0] = 11; mat2[2][1] = 12;
//ispisem
ispis(mat2, n2, m2);
//matrica 3 ce biti proizvod ovih 2, saljem matrice i velicinu
int** mat3 = proizvod(mat1,n1,m1, mat2, n2, m2);
//vrste iz prve a kolone iz druge
//ispisem
ispis(mat3, n1, m2);
obrisi(mat1, n1);
obrisi(mat2, n2);
obrisi(mat3, n1);
return 0;
}
//ispisem matricu
void ispis(int** mat,int n,int m) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
printf("%d ", mat[j]);
}
putchar('\n');
}
putchar('\n');
}
/*
* Racuanje proizvoda matrice na sledeci nacin
* Alociram matricu velicine n1xm2 jer to je velicina pomnozene matrice
* onda idemo kroz tu matricu i dodajemo na vrednost polja proizvod
* prve i druge matrice, na kraju vratimo matricu
*/
int** proizvod(int** mat1, int n1, int m1, int** mat2,int n2,int m2) {
//alociranje matrice
int** mat = (int**)calloc(n1, sizeof(int*));
for (int i = 0; i < n1; i++) {
mat = (int*)calloc(m2, sizeof(int));
}
//petlja koja ce proci kroz celu matricu
for (int i = 0; i < n1; i++) {
for (int j = 0; j < m2; j++) {
//za svako polje idemo kroz kolone prve i vrste druge
for (int k = 0; k < n2; k++) {
//na matricu dodajemo proizvod ta 2 broja
mat[j] += mat1[k] * mat2[k][j];
}
}
}
//vratimo matricu
return mat;
}

void obrisi(int** mat, int n) {
for (int i = 0; i < n; i++) {
free(mat);
}
free(mat);
}
 
Jel se zezaš ili ozbiljno?
Nulu kod množenja dobijaš samo ako je neki element matrice jednak nuli.
Negativan broj samo ako je rezultat veći od maxint.

Gledam na brzinu, ali zašto upotrebljavaš kolone 2 puta za množenje i dodaješ na postojeću vrednost?

Probaj neki debug ispis u stilu: kolona_x(vrednost) * red_y(vrednost) = rezultat_z, pa vidi dalje...
Uhm, ne dobija negativno jer mnozi sa negativnim vec zato sto ima JUNK vrednost. Ono sto prikazuje je max za unsigned int, a to je negativan broj u signed int.
Takodje, mora da mnogi tako sto dodaje, to je mnozenje matrice. Red jedne s kolonom jedne pa njihov zbir.
 
Evo ti mnozenje mat4x4 u asembler-u ;)
Kod:
Mul:     mov ecx,4 
.L0:     vpxor ymm0,ymm0,ymm0   
          xor r9d,r9d    xor r8d,r8d 
.L1:    vbroadcastsd ymm1, [rsi+r9*8]
          vmovupd ymm2,[rdx+r8]
          inc r9d
         add r8,32 
          vfmadd231pd ymm0,ymm2,ymm1
          cmp r9d,4    
          jl .L1 
          vmovupd [rdi],ymm0
          add rsi,32
          add rdi,32
          dec ecx
          jnz .L0    
          ret
rdi,rsi,rdx su paremetri na Linux-u. rdi dest matrica rsi,rdx izvor.
 
Evo ti mnozenje mat4x4 u asembler-u ;)
Kod:
Mul:     mov ecx,4
.L0:     vpxor ymm0,ymm0,ymm0  
          xor r9d,r9d    xor r8d,r8d
.L1:    vbroadcastsd ymm1, [rsi+r9*8]
          vmovupd ymm2,[rdx+r8]
          inc r9d
         add r8,32
          vfmadd231pd ymm0,ymm2,ymm1
          cmp r9d,4   
          jl .L1
          vmovupd [rdi],ymm0
          add rsi,32
          add rdi,32
          dec ecx
          jnz .L0   
          ret
rdi,rsi,rdx su paremetri na Linux-u. rdi dest matrica rsi,rdx izvor.
Sad jos neko da mu doda RUST i to je to :)
 

Back
Top