德国开元华人社区 开元周游

标题: 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 />   =&gt; 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 />   =&gt; 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 />   =&gt; 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 />   =&gt; 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 />   =&gt; 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. &quot;Sicher&quot;<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&#33;<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&lt;=m-1; i++)<br />    for (j=0; j&lt;=k-1; j++)<br />      { u=i*k+j; c=0.0;<br />        for (l=0; l&lt;=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 &lt;stdio.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;string.h&gt;<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&lt;n1;i++,a+=n2,b-=n3) {    <br />    for(m = 0; m&lt;n3; m++,b-=n2*n3-1, a-=n2, *c++=sum, sum=0;) {<br />      for(j = 0; j&lt;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(&quot;=&gt; v3:\n&quot;);<br />  for(i = 1; i&lt;=n1*n3;i++) {<br />    printf(&quot;%f&quot;, *c++);<br />    if(i % n3 == 0) {<br />      printf(&quot;\n&quot;);<br />    }else {<br />      printf(&quot; &quot;);<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&copy;;<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&copy;;<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&copy;;<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://bbs.kaiyuan.cn/) Powered by Discuz! X3.2