德国开元华人社区 开元周游
标题:
C++菜鸟求助
[打印本页]
作者:
路过
时间:
21.11.2005 14:59
<span style='color:blue'>老师给了一个关于矩阵相乘的aufgabe,本来这个东西并不很难,可是里面牵扯到了指针我就犯傻了,我是初学者,希望能有人指点一下该怎么做,明天就要交了啦。多谢了!</span><br /><br />Aufgabe 3a)<br />===========<br />Das Produkt einer n1xn2 Matrix A und einer n2xn3 Matrix B ist eine n1xn3 Matrix<br />C mit den Komponenten<br />c
[j]=a
[0]*b[0][j]+a
[1]*b[1][j]+...+a
[n2-1]*b[n2-1][j]<br /><br />Es soll eine Funktion matmul geschrieben werden, mit der man beliebige Matrizen<br />(zweidimensionale double-Felder) multiplizieren kann, wobei nur vorausgesetzt<br />wird, dass die Spaltenzahl des ersten Feldes gleich der Zeilenzahl des zweiten<br />ist.<br /><br />Eine Funktion, die eine 3x2 Matrix A mit einer 2x4 Matrix B multipliziert, was<br />eine 3x4 Matrix C ergibt, koennte so definiert werden:<br />void matmul(double A[][2],double B[][4],double C[][4]) {...}<br />Da hier die erste Dimension der Felder A, B und C nicht in den Datentyp der<br />formalen Parameter eingeht, kann man diese Funktion leicht verallgemeinern zu<br />einer Funktion, die eine n1x2 Matrix A mit einer 2x4 Matrix B multipliziert,<br />was eine n1x4 Matrix C ergibt:<br />void matmul(double A[][2],double B[][4],double C[][4],int n1) {...}<br />Damit ist noch nicht viel gewonnen. Die Funktion ist immer noch viel zu <br />speziell. Z.B. kann man damit keine 3x3 mit einer 3x3 Matrix multiplizieren.<br /><br />Der Aufruf einer brauchbaren Funktion zur Multiplikation einer beliebigen<br />n1xn2 Matrix A mit einer n2xn3 Matrix B sollte so aussehen:<br />matmul(A,B,C,n1,n2,n3);<br />Hierzu muss man die Funktion wie folgt definieren:<br /><br />void matmul(void *A,void *B,void *C,int n1,int n2,int n3)<br />{<br />double *a=(double*)A,*b=(double*)B,*c=(double*)C;<br /> :<br /> :<br />}<br /><br />An einen Pointer auf void kann man jeden beliebigen (nicht const und nicht<br />volatile) Pointer-Typ ohne cast zuweisen. Deshalb kann man die Funktion mit<br />beliebeigen Feld-Typen als aktuellen Parametern fuer die void*-Parameter<br />aufgerufen werden. Die void*-Parameter erhalten beim Aufruf der Funktion als<br />Werte die Anfangs-Adressen der Speicherbereiche fuer die Felder A, B und C.<br />In der Funktion werden diese Adressen zunaechst ueber einen cast umgewandelt<br />in Pointer auf double. Damit kann man a, b und c in der Funktion verwenden wie<br />eindimensionale Felder der Speicherbereiche der zweidimensionalen Felder A, B<br />und C. Ein doppelt indizierter Zugriff muss dann gemaess der Speicherabbildung<br />in einen einfach indizierten Zugriff umgewandelt werden.<br /><br />Erstellen Sie die Funktion matmul und eine main-Funktion zum Test von matmul.<br /><br />Hier noch einige Spezialfaelle des Matrizen-Produktes:<br /><br />1) Inneres Produkt (Skalarprodukt) zweier Vektoren:<br /> 1xn2 Matrix mal n2x1 Matrix ergibt 1x1 Matrix, d.h. Skalar.<br /> double v1[1][3]={1,2,3},v2[3][1]={4,5,6},v3[1][1];<br /> matmul(v1,v2,v3,1,3,1);<br /> => v3 : 32<br /><br />2) Aeusseres Produkt (Tensorprodukt) zweier Vektoren:<br /> n1x1 Matrix mal 1xn3 Matrix ergibt n1xn3 Matrix.<br /> double v1[3][1]={1,2,3},v2[1][3]={4,5,6},v3[3][3];<br /> matmul(v1,v2,v3,3,1,3);<br /> 4 5 6<br /> => v3 : 8 10 12 <br /> 12 15 18<br /><br />3) Produkt eines Skalars mit einem Vektor:<br /> 1x1 Matrix mal 1xn3 Matrix ergibt 1xn3 Matrix.<br /> double v1[1][1]={2},v2[1][3]={1,2,3},v3[1][3];<br /> matmul(v1,v2,v3,1,1,3);<br /> => v3 : 2 4 6<br /><br />4) Produkt eines Vektors mit einem Skalar:<br /> n1x1 Matrix mal 1x1 Matrix ergibt n1x1 Matrix.<br /> double v1[3][1]={1,2,3},v2[1][1]={2},v3[3][1];<br /> matmul(v1,v2,v3,3,1,1);<br /> 2<br /> => v3 : 4<br /> 6<br /><br />5) Produkt eines Skalars mit einem Skalar:<br /> 1x1 Matrix mal 1x1 Matrix ergibt 1x1 Matrix.<br /> double v1[1][1]={2},v2[1][1]={3},v3[1][1];<br /> matmul(v1,v2,v3,1,1,1);<br /> => v3 : 6<br /><br />Aufgabe 3b)<br />===========<br />Schreiben Sie eine Funktion <br />void safematmul(void *A,void *B,void *C,int n1,int n2,int n3) {...}<br />Diese soll eine sichere Version der matmul-Funktion von aufg01 sein. "Sicher"<br />soll dabei bedeuten, dass die Funktion auch dann noch richtig arbeitet, wenn<br />einer der beiden Faktoren gleichzeitig als Ergebnis angegeben wird. D.h. auch<br />die Aufrufe<br />matmul(a,b,a,n1,n2,n3);<br />matmul(a,b,b,n1,n2,n3);<br />matmul(a,a,a,n1,n2,n3);<br />sollen richtige Ergebnisse liefern.<br />Hinweis: Sie muessen fuer das Ergebnis (Produktmatrix) zunaechst mit new Spei-<br />cherplatz bereitstellen. In diesen Hilfsspeicher wird das Ergebnis geschrieben.<br />Erst ganz zum Schluss der Rechnung wird das Ergebnis dann in den Speicherbe-<br />reich der eigentlichen Ergebnisvariablen kopiert. Hierzu koennen Sie memcpy von<br />aufg02 verwenden.<br />Vergessen Sie nicht, den mit new angeforderten Speicherbereich am Ende der <br />Funktion mit delete wieder freizugeben!<br />Testen Sie Ihr Programm.
作者:
wl468dedede
时间:
21.11.2005 19:21
void brmul(a,b,c,m,n,k)<br /> int m,n,k;<br /> double a[],b[],c[];<br /> { int i,j,l,u;<br /> for (i=0; i<=m-1; i++)<br /> for (j=0; j<=k-1; j++)<br /> { u=i*k+j; c
=0.0;<br /> for (l=0; l<=n-1; l++)<br /> c
=c
+a[i*n+l]*b[l*k+j];<br /> }<br /> return;<br /> }<br />
作者:
嗯嗯啊啊
时间:
21.11.2005 20:18
eine einfachere und wesentliche effiziente Version findest du unten<br /><br />1. Wenn du nur matmal testen willst, bitte kompilier wie folgendes<br /><br /> gcc -DTEST_MATMUL -o matmul matmul.cpp<br /><br />2. Wenn du nur saftmatmul testest, dann nur<br /><br /> gcc -o matmul matmul.cpp<br /><br /><br />wenn noch was dir nicht klar ist, gib mir deine msn. ich erkläre es dir online-<br />ich habe es bereits mit allen beispiel aus deinem aufgabezettel getestet. Es funktioniert ganz gut-<br /><br />matmul.cpp<br /><br />#include <stdio.h><br />#include <stdlib.h><br />#include <string.h><br /><br />void output(void*, int, int);<br /><br />void matmul(void *A,void *B,void *C,int n1,int n2,int n3)<br />{<br /> double *a=(double*)A;<br /> double *b=(double*)B;<br /> double *c=(double*)C;<br /> double sum = 0;<br /> int i = 0;<br /> int j = 0;<br /> int m = 0;<br /><br /> for(i = 0; i<n1;i++,a+=n2,b-=n3) { <br /> for(m = 0; m<n3; m++,b-=n2*n3-1, a-=n2, *c++=sum, sum=0;) {<br /> for(j = 0; j<n2; j++,b+=n3) {<br /> sum += *a++ * *b;<br /> } <br /> } <br /> } <br /><br />#ifdef TEST_MATMUL /* turn on if u want to test matmal() */<br /> c -= n1*n3;<br /> output(c, n1, n3);<br />#endif<br />}<br /><br />void output(void *M, int n1, int n3) {<br /> int i;<br /> double *c = (double *)M;<br /><br /> printf("=> v3:\n");<br /> for(i = 1; i<=n1*n3;i++) {<br /> printf("%f", *c++);<br /> if(i % n3 == 0) {<br /> printf("\n");<br /> }else {<br /> printf(" ");<br /> }<br /> }<br />}<br /><br />void safematmul(void *A,void *B,void *C,int n1,int n2,int n3) {<br /> double *a, *b, *c;<br /> a = (double *)A;<br /> b = (double *)B;<br /> <br /> if(A==C) {<br /> c = (double *)malloc(sizeof(double)*n1*n3);<br /> matmul(a, b, c, n1, n2, n3);<br /> realloc(a, n1*n3*sizeof(char));<br /> memcpy(a, c, n1*n3*sizeof(char));<br />#ifndef TEST_MATMUL<br /> output(a, n1, n3);<br />#endif<br /> free©;<br /> }else if(B==C) {<br /> c = (double *)malloc(sizeof(double)*n1*n3);<br /> matmul(a, b, c, n1, n2, n3);<br /> realloc(b, n1*n3*sizeof(char));<br /> memcpy(b, c, n1*n3*sizeof(char));<br />#ifndef TEST_MATMUL<br /> output(b, n1, n3);<br />#endif<br /> free©;<br /> }else if(A==<!--emo&B)--><img src='style_emoticons/<#EMO_DIR#>/cool.gif' border='0' style='vertical-align:middle' alt='cool.gif' /><!--endemo--> {<br /> c = (double *)malloc(sizeof(double)*n1*n3);<br /> matmul(a, b, c, n1, n2, n3);<br /> memcpy(a,c, n1*n3*sizeof(char));<br />#ifndef TEST_MATMUL<br /> output(b, n1, n3);<br />#endif<br /> free©;<br /> }else {<br /> c = (double *)C;<br /> matmul(a, b, c, n1, n2, n3);<br />#ifndef TEST_MATMUL<br /> output(c, n1, n3);<br />#endif<br /> }<br />}<br /><br />int main(int argc, char **argv) {<br />#ifdef TEST_MATMUL<br /> double v1[1][3]={1,2,3},v2[3][1]={4,5,6},v3[1][1];<br /> matmul(v1,v2,v3,1,3,1);<br />#else<br /> double v1_s[3][1]={1,2,3},v2_s[1][1]={2}, v3[3][1];<br /> double *v1;<br /> double *v2;<br /> int d1, d2, d3, d4;<br /> d1 = 3;<br /> d2 = 1;<br /> v1 = (double*)malloc(d1*d2*sizeof(double));<br /> v2 = (double*)malloc(d1*d1*sizeof(double));<br /> <br /> memcpy(v1, v1_s, d1*d2*sizeof(double));<br /> memcpy(v2, v2_s, d1*d1*sizeof(double));<br /> safematmul(v1_s,v2_s,v3,3,1,1); <br /> free(v1);<br /> free(v2);<br />#endif<br />}
作者:
路过
时间:
22.11.2005 02:00
多谢两位牛人,我先去好好研究一下,谢谢啦!
欢迎光临 德国开元华人社区 开元周游 (https://forum.kaiyuan.de/)
Powered by Discuz! X3.2