ページ 11

前の続きです・・・行列

Posted: 2012年5月10日(木) 21:39
by れお
前のを解決にしてしまったんですが、まだ解決してませんでした><

コード:

//n×n正方行列Aに対して、Aのk乗を求めるプログラム
 #include <stdio.h>
 #define N 5

 void Input_matrix(float (*X)[N],int n) 
 {
     int i=0,j=0;
     for(i=0;i<n;i++)
     {
         for(j=0;j<n;j++)
         {
             printf("行列Aの%d行%d列成分の値を入力してください\n",i+1,j+1);
             scanf("%f",&X[i][j]);
         }
     }

     return ;
 }


 void Multiply_matrix(float (*X)[N],float (*Y)[N],float (*Z)[N],float (*W)[N],int n,int k)
 {
     int h=0,i=0,j=0,p=0;
     if(k==1)
     {
         for(i=0;i<n;i++)
         {
             for(j=0;j<n;j++)
             {
                 Z[i][j]=X[i][j];
             }
         }
    	 return;
     }
     else
     {
    	 for(i=0;i<n;i++)
    	 {
    		 for(j=0;j<n;j++)
    		 {
    			 for(p=0;p<n;p++)
    			 {
    				 Z[i][j]+=X[i][p]*Y[p][j];
    			 }
    		 }
    	 }
    	 if(k==2)
    	 {
    		 return;
    	 }
    	 else//累乗
    	 {
    		 for(h=2;h<k;h++)
			 {
				 for(i=0;i<n;i++)
				 {
					 for(j=0;j<n;j++)
					 {
						 for(p=0;p<n;p++)
						 {
							 W[i][j]+=Z[i][p]*Y[p][j];
						 }						 }
				 }
				 for(i=0;i<n;i++)
				 {
					 for(j=0;j<n;j++)
					 {
						 Z[i][j]=W[i][j];
						 W[i][j]=0;
					 }
				 }
			 }
    	 }
     return;
     }
 }

 void Print_matrix(float (*Y)[N], int n)
 {
     int i=0, j=0;
     for (i = 0; i < n; i++) {
         for (j = 0; j < n; j++) {
             printf("[%d][%d]=%f\n", i + 1, j + 1, Y[i][j]);
         }
     }
     return;
 }



 int main(void)
 {
     float X[N][N]={{0}},Y[N][N]={{0}},Z[N][N]={{0}};
     int n=0,k=0;
     printf("n(0<n<=5 nは整数)を決めてください。n=");
     scanf("%d",&n);

     if(n>5||n<=0)
     {
         printf("エラー:n<=5となるnを入力してください\n");
         return (-1);
     }

     Input_matrix(X,n);//行列の入力

     printf("k乗なるk(kは自然数)を入力してください\n[行][列]\n");
     scanf("%d",&k);
     if(k<=0)
     {
    	 printf("エラー:kは自然数です");
    	 return(-1);
     }

     Multiply_matrix(X,X,Y,Z,n,k);//行列の計算

     Print_matrix(Y, n);

     return 0;
 }

これは行列を累乗するプログラムなのですが、行列をコピーしてk乗してます。
でもこれをポインタを使ってコピーせずにk乗したいのです><
あとkが奇数、偶数のときで場合わけしなくてもいいようにしないといけないです・・・

(**p)[ ]という風なものをつかうようなのですが、今いちこの意味もわかってません。。。

どなたかお願いします

Re: 前の続きです・・・行列

Posted: 2012年5月10日(木) 21:56
by beatle
具体的にはどこでコピーしているのでしょうか。
ちゃんとポインタで渡せているように見えるのですが。

Re: 前の続きです・・・行列

Posted: 2012年5月10日(木) 22:05
by box
そもそも、Multiple_matrix()に渡している引数で、
行列そのものに関するものがどうして4つも必要なのかが
全くわからない、というのは、確か前のトピックでかずまさんかどなたかが
指摘されていたとおりです。

行列Xの累乗を求めた結果を行列Yに入れればよいだけのことであって、
引数としては4つもいらないはずです。

まあ、ご自分のコードにこだわりたいお気持ちはわからなくはありませんが、
よろしければ前のトピックで私が書いたコードをそのまま差し上げますので、
引数の型をfloatにするなりなんなり、ご自由に改変してくださってかまいません。

どうしてもご自分で作りたい!という強い意志がおありなら、
設計をやり直すことをおすすめします。

Re: 前の続きです・・・行列

Posted: 2012年5月10日(木) 22:09
by みけCAT
行列をコピーしないで累乗するのは、私には難しいです。
とりあえず、場合分けしないコードを書いてみました。
Multiple_matrix関数を以下のコードに置き換えてください。

コード:

void Multiply_matrix(float (*X)[N],float (*Y)[N],float (*Z)[N],float (*W)[N],int n,int k)
{
	float RB1[N][N]={{0}};
	float RB2[N][N]={{0}};
	float B1[N][N]={{0}};
	float B2[N][N]={{0}};
	float (*BS)[N]=B1;
	float (*BD)[N]=B2;
	float (*RBS)[N]=RB1;
	float (*RBD)[N]=RB2;
	float (*temp)[N];
	int h=0,i=0,j=0,p=0;
	for(i=0;i<n;i++)
	{
		RBS[i][i]=1;
		for(j=0;j<n;j++)
		{
			BS[i][j]=X[i][j];
		}
	}
	for(;k>0;k>>=1) {
		if(k & 1) {
			for(i=0;i<n;i++)
			{
				for(j=0;j<n;j++)
				{
					RBD[i][j]=0;
					for(p=0;p<n;p++)
					{
						RBD[i][j]+=RBS[i][p]*BS[p][j];
					}
				}
			}
			temp=RBS;RBS=RBD;RBD=temp;
		}
		for(i=0;i<n;i++)
		{
			for(j=0;j<n;j++)
			{
				BD[i][j]=0;
				for(p=0;p<n;p++)
				{
					BD[i][j]+=BS[i][p]*BS[p][j];
				}
			}
		}
		temp=BS;BS=BD;BD=temp;
	}
	for(i=0;i<n;i++)
	{
		for(j=0;j<n;j++)
		{
			Z[i][j]=RBS[i][j];
		}
	}
	return;
}
オフトピック
れおさんが書かれたプログラムと、私が書いたプログラム。
Xに単位行列または零行列、kに16777216を入れて、
答えが出るまでの時間を比較するとどうなるでしょうか?

Re: 前の続きです・・・行列

Posted: 2012年5月10日(木) 23:01
by れお
beatleさん 68行目です(このレスでは49行目です)!このコピーをしてはいけないという条件なんです・・・

boxさん boxさんが書いたプログラムは自分の実力ではまだ理解できないのです・・・
      調べてもいまいちmemset などがわからないもので・・・;;
      なのでかずまさんのを利用することにしてみます。
      自分のにもそこまではこだわりないのですが、自分のじゃないと理解できないことが多かったり、理解するのにかなり      時間がかかるので><

みけCATさん 課題の条件がコピーせずにポインタを利用してやることなんです。><

一応前すれのかずまさんのを用いて書き換えました。

コード:

//n×n正方行列Aに対して、Aのk乗を求めるプログラム
 #include <stdio.h>
 #define N 5

 void Input_matrix(float (*X)[N],int n)   //2次元配列のポインタ。後ろのほうしか必要じゃない
 {
     int i=0,j=0;
     for(i=0;i<n;i++)
     {
         for(j=0;j<n;j++)
         {
             printf("行列Aの%d行%d列成分の値を入力してください\n",i+1,j+1);
             scanf("%f",&X[i][j]);
         }
     }

     return ;
 }


 void Multiply_matrix(float (*X)[N],float (*Y)[N],int n,int k)
 {
     int h=0,i=0,j=0,p=0;
     float W[N][N];
     for (i = 0; i < n; i++)
     {
    	 for (j = 0; j < n; j++)
    	 {
    		 Y[i][j] = X[i][j];
    	 }
     }
     for (h = 1; h < k; h++)//k=1ではおこらない
     {
    	 for (i = 0; i < n; i++)
    	 {
    		 for (j = 0; j < n; j++)
    		 {
    			 W[i][j] = 0;//いちいち初期化しないと計算の時余分に足してしまう
    			 for (p = 0; p < n; p++)
    			 {
    				 W[i][j] += Y[i][p] * X[p][j];
    			 }
    		 }
    	 }
    	 for (i = 0; i < n; i++)
    	 {
    		 for (j = 0; j < n; j++)
    		 {
    			 Y[i][j] = W[i][j];
    		 }
    	 }
     }
 }

 void Print_matrix(float (*Y)[N], int n)
 {
     int i=0, j=0;
     for (i = 0; i < n; i++) {
         for (j = 0; j < n; j++) {
             printf("[%d][%d]=%f\n", i + 1, j + 1, Y[i][j]);
         }
     }
     return;
 }



 int main(void)
 {
     float X[N][N]={{0}},Y[N][N]={{0}};//初期化しないと行列計算の時おかしくなる
     int n=0,k=0;
     printf("n(0<n<=5 nは整数)を決めてください。n=");
     scanf("%d",&n);

     if(n>5||n<=0)
     {
         printf("エラー:n<=5となるnを入力してください\n");
         return (-1);
     }

     Input_matrix(X,n);//行列の入力

     printf("k乗なるk(kは自然数)を入力してください\n[行][列]\n");
     scanf("%d",&k);
     if(k<=0)
     {
    	 printf("エラー:kは自然数です");
    	 return(-1);
     }

     Multiply_matrix(X,Y,n,k);//行列の計算

     Print_matrix(Y, n);

     return 0;
 }



Re: 前の続きです・・・行列

Posted: 2012年5月10日(木) 23:11
by box
れお さんが書きました: boxさん boxさんが書いたプログラムは自分の実力ではまだ理解できないのです・・・
      調べてもいまいちmemset などがわからないもので・・・;;
くだんのコードにおいては、memset()は「全部ゼロにしてください」、
memcpy()は「とにかく丸ごとコピーしてください」という程度の使い方しかしていません。

Re: 前の続きです・・・行列

Posted: 2012年5月11日(金) 00:46
by れお
なるほど。理解しました。
また明日早いので明日あたりにみなおします。。

ありがとうございます!!

Re: 前の続きです・・・行列

Posted: 2012年5月11日(金) 08:22
by みけCAT
こんな感じでどうでしょうか?
kが「奇数、偶数のとき」での場合わけもありません。

コード:

//n×n正方行列Aに対して、Aのk乗を求めるプログラム
#include <stdio.h>
#define N 5

void Input_matrix(float (*X)[N],int n)   //2次元配列のポインタ。後ろのほうしか必要じゃない
{
	int i=0,j=0;
	for(i=0;i<n;i++)
	{
	for(j=0;j<n;j++)
		{
			printf("行列Aの%d行%d列成分の値を入力してください\n",i+1,j+1);
			scanf("%f",&X[i][j]);
		}
	}

	return ;
}

void Multiply_matrix(float (*X)[N],float (*Y)[N],int n,int k)
{
	float RB[N][N]={{0}};
	float B1[N][N]={{0}};
	float B2[N][N]={{0}};
	float (*BS)[N]=X;
	float (*BD)[N]=B2;
	float (*RBS)[N]=RB;
	float (*RBD)[N]=Y;
	float (*temp)[N];
	int i=0,j=0,p=0;
	int bits=k;
	bits=((bits & 0x2AAAAAAA)>>1) + (bits & 0x55555555);
	bits=((bits & 0x4CCCCCCC)>>2) + (bits & 0x33333333);
	bits=((bits & 0x70F0F0F0)>>4) + (bits & 0x0F0F0F0F);
	bits=((bits & 0x7F00FF00)>>8) + (bits & 0x00FF00FF);
	bits=((bits & 0x7FFF0000)>>16)+ (bits & 0x0000FFFF);
	if(bits%2==0){temp=RBS;RBS=RBD;RBD=temp;}
	for(i=0;i<n;i++)
	{
		for(j=0;j<n;j++)
		{
			RBS[i][j]=(i==j)?1:0;
		}
	}
	for(;k>0;k>>=1) { // k>>=1はk/=2にしても可 
		if(k & 1) {   // k & 1はk%2にしても可 
			for(i=0;i<n;i++)
			{
				for(j=0;j<n;j++)
				{
					RBD[i][j]=0;
					for(p=0;p<n;p++)
					{
						RBD[i][j]+=RBS[i][p]*BS[p][j];
					}
				}
			}
			temp=RBS;RBS=RBD;RBD=temp;
		}
		for(i=0;i<n;i++)
		{
			for(j=0;j<n;j++)
			{
				BD[i][j]=0;
				for(p=0;p<n;p++)
				{
					BD[i][j]+=BS[i][p]*BS[p][j];
				}
			}
		}
		if(BS==X)BS=B1;
		temp=BS;BS=BD;BD=temp;
	}
	return;
}

void Print_matrix(float (*Y)[N], int n)
{
	int i=0, j=0;
	for (i = 0; i < n; i++) {
		for (j = 0; j < n; j++) {
			printf("[%d][%d]=%f\n", i + 1, j + 1, Y[i][j]);
		}
	}
	return;
}



int main(void)
{
	float X[N][N]={{0}},Y[N][N]={{0}};//初期化しないと行列計算の時おかしくなる
	int n=0,k=0;
	printf("n(0<n<=5 nは整数)を決めてください。n=");
	scanf("%d",&n);

	if(n>5||n<=0)
	{
		printf("エラー:n<=5となるnを入力してください\n");
		return (-1);
	}

	Input_matrix(X,n);//行列の入力

	printf("k乗なるk(kは自然数)を入力してください\n[行][列]\n");
	scanf("%d",&k);
	if(k<=0)
	{
		printf("エラー:kは自然数です");
		return(-1);
	}

	Multiply_matrix(X,Y,n,k);//行列の計算

	Print_matrix(Y, n);

	return 0;
}

Re: 前の続きです・・・行列

Posted: 2012年5月11日(金) 13:05
by beatle
取り敢えず書いてみました。
ミソはMatrix構造体のなかにデータへのポインタを組み込んだことです。
さらにその構造体をstruct Matrix*型で受け取る事で、ダブルポインタ(int **)を分かりやすく実現しています。

コード:

#include <stdio.h>
#include <stdlib.h>

#define SUCCESS 0
#define ERROR 1

typedef int ElemType;

struct Matrix
{
    size_t nrow, ncol;
    ElemType* data;
};

struct Matrix NewMatrix(size_t nrow, size_t ncol)
{
    struct Matrix m;
    m.nrow = nrow;
    m.ncol = ncol;
    m.data = (ElemType*)malloc(nrow * ncol * sizeof(ElemType));
    return m;
}

void DeleteMatrix(struct Matrix* m)
{
    free(m->data);
    m->data = NULL;
}

ElemType GetElement(struct Matrix* m, size_t i, size_t j)
{
    return m->data[i * m->ncol + j];
}

void SetElement(struct Matrix* m, size_t i, size_t j, ElemType elem)
{
    m->data[i * m->ncol + j] = elem;
}

struct Matrix Multiply(struct Matrix* lhs, struct Matrix* rhs)
{
    if (lhs->ncol != rhs->nrow)
    {
        struct Matrix m;
        m.nrow = m.ncol = 0;
        m.data = NULL;
        return m;
    }

    struct Matrix result = NewMatrix(lhs->nrow, lhs->ncol);
    result.nrow = lhs->nrow;
    result.ncol = rhs->ncol;

    for (size_t i = 0; i < result.nrow; ++i)
    {
        for (size_t j = 0; j < result.ncol; ++j)
        {
            ElemType elem = 0;
            for (size_t k = 0; k < lhs->ncol; ++k)
            {
                elem += GetElement(lhs, i, k) * GetElement(rhs, k, j);
            }
            SetElement(&result, i, j, elem);
        }
    }

    return result;
}

void PrintMatrix(struct Matrix* m)
{
    printf("%d x %d matrix\n", (int)m->nrow, (int)m->ncol);
    for (size_t i = 0; i < m->nrow; ++i)
    {
        for (size_t j = 0; j < m->ncol; ++j)
        {
            printf("[%d][%d]=%d\n", (int)i, (int)j, (int)GetElement(m, i, j));
        }
    }
}

int main(void)
{
    struct Matrix mx = NewMatrix(2, 2);
    struct Matrix my = NewMatrix(2, 2);
    struct Matrix mz;

    SetElement(&mx, 0, 0, 1);
    SetElement(&mx, 0, 1, 2);
    SetElement(&mx, 1, 0, 3);
    SetElement(&mx, 1, 1, 4);
    PrintMatrix(&mx);

    SetElement(&my, 0, 0, 1);
    SetElement(&my, 0, 1, 1);
    SetElement(&my, 1, 0, 0);
    SetElement(&my, 1, 1, 1);
    PrintMatrix(&my);

    mz = Multiply(&mx, &my);
    PrintMatrix(&mz);

    DeleteMatrix(&mx);
    DeleteMatrix(&my);
    DeleteMatrix(&mz);
}

Re: 前の続きです・・・行列

Posted: 2012年5月11日(金) 19:15
by れお
ありがとうございます。
でもなんかポインタのポインタをりようしないといけないらしいです><

(**p)みたいなやつです・・・

Re: 前の続きです・・・行列

Posted: 2012年5月11日(金) 21:24
by みけCAT
こんな感じですか?

コード:

//n×n正方行列Aに対して、Aのk乗を求めるプログラム
#include <stdio.h>
#define N 5

void Input_matrix(float **X,int n)   //2次元配列のポインタ。後ろのほうしか必要じゃない
{
	int i=0,j=0;
	for(i=0;i<n;i++)
	{
	for(j=0;j<n;j++)
		{
			printf("行列Aの%d行%d列成分の値を入力してください\n",i+1,j+1);
			scanf("%f",&X[i][j]);
		}
	}

	return ;
}

void Multiply_matrix(float **X,float **Y,int n,int k)
{
	float RB[N][N]={{0}};
	float B1[N][N]={{0}};
	float B2[N][N]={{0}};
	float *BS[N];
	float *BD[N];
	float *RBS[N];
	float *RBD[N];
	float *temp;
	int i=0,j=0,p=0;
	int bits=0;
	bool start=true;

	for(i=0;i<N;i++) {
		BS[i]=X[i];
		BD[i]=(float*)&B2[i];
		RBS[i]=(float*)&RB[i];
		RBD[i]=Y[i];
	}

	bits=k;
	bits=((bits & 0x2AAAAAAA)>>1) + (bits & 0x55555555);
	bits=((bits & 0x4CCCCCCC)>>2) + (bits & 0x33333333);
	bits=((bits & 0x70F0F0F0)>>4) + (bits & 0x0F0F0F0F);
	bits=((bits & 0x7F00FF00)>>8) + (bits & 0x00FF00FF);
	bits=((bits & 0x7FFF0000)>>16)+ (bits & 0x0000FFFF);
	if(bits%2==0) {
		for(i=0;i<N;i++) {
			temp=RBS[i];
			RBS[i]=RBD[i];
			RBD[i]=temp;
		}
	}
	for(i=0;i<n;i++)
	{
		for(j=0;j<n;j++)
		{
			RBS[i][j]=(i==j)?1:0;
		}
	}
	for(;k>0;k>>=1) { // k>>=1はk/=2にしても可 
		if(k & 1) {   // k & 1はk%2にしても可 
			for(i=0;i<n;i++)
			{
				for(j=0;j<n;j++)
				{
					RBD[i][j]=0;
					for(p=0;p<n;p++)
					{
						RBD[i][j]+=RBS[i][p]*BS[p][j];
					}
				}
			}
			for(i=0;i<N;i++) {
				temp=RBS[i];
				RBS[i]=RBD[i];
				RBD[i]=temp;
			}
		}
		for(i=0;i<n;i++)
		{
			for(j=0;j<n;j++)
			{
				BD[i][j]=0;
				for(p=0;p<n;p++)
				{
					BD[i][j]+=BS[i][p]*BS[p][j];
				}
			}
		}
		if(start) {
			for(i=0;i<N;i++) {
				BS[i]=(float*)&B1[i];
			}
			start=false;
		}
		for(i=0;i<N;i++) {
			temp=BS[i];
			BS[i]=BD[i];
			BD[i]=temp;
		}
	}
	return;
}

void Print_matrix(float **Y, int n)
{
	int i=0, j=0;
	for (i = 0; i < n; i++) {
		for (j = 0; j < n; j++) {
			printf("[%d][%d]=%f\n", i + 1, j + 1, Y[i][j]);
		}
	}
	return;
}



int main(void)
{
	float X[N][N]={{0}},Y[N][N]={{0}};//初期化しないと行列計算の時おかしくなる
	int n=0,k=0;
	float *pX[N],*pY[N];
	int i=0;

	for(i=0;i<N;i++) {
		pX[i]=(float*)&X[i];
		pY[i]=(float*)&Y[i];
	}

	printf("n(0<n<=5 nは整数)を決めてください。n=");
	scanf("%d",&n);

	if(n>5||n<=0)
	{
		printf("エラー:n<=5となるnを入力してください\n");
		return (-1);
	}

	Input_matrix(pX,n);//行列の入力

	printf("k乗なるk(kは自然数)を入力してください\n[行][列]\n");
	scanf("%d",&k);
	if(k<=0)
	{
		printf("エラー:kは自然数です");
		return(-1);
	}

	Multiply_matrix(pX,pY,n,k);//行列の計算

	Print_matrix(pY, n);

	return 0;
}

Re: 前の続きです・・・行列

Posted: 2012年5月13日(日) 18:49
by れお
ん~
うまく説明できない・・・><

とりあえず今回はちょっと条件からはずれてますが、前のスレのboxさんのかりさせていただきます。
memcpy memsetの勉強にもなったしそれを参考にして提出します。


みなさんありがとうございました^^

Re: 前の続きです・・・行列

Posted: 2012年5月16日(水) 20:07
by れお
宿題とは関係なしにポインタをつかってやってみました
Power_matrixでの引数のひとつをポインタのポインタでやるみたいです。
自分なりにやったのですが、答えがあきらかにおかしいです。ビルドエラーとかはないのですが・・・
どこがおかしいのか自分ではかなり考えたんですがわかりません
どなたか訂正お願いします。
また次課題がでるのでできるだけ早くこれは解決したいです;
お願いします。
だいたい自分がやったようなコードであってるはずなので、これをもとに考えていただくとありがたいです。
おそらくPower_matrixの中身だけかえればいけるとおもうのですが・・・
Z=X*X
Y=Z*X
YとZの中身を交換
Z=Y*X
というふうにやりたいです。

コード:

#include <stdio.h>
#define N 5

void Input_matrix(float(*X)[N], int n) //2次元配列のポインタ。後ろのほうしか必要じゃない
{
	int i = 0, j = 0;
	for (i = 0; i < n; i++) {
		for (j = 0; j < n; j++) {
			printf("行列Aの%d行%d列成分の値を入力してください\n", i + 1, j + 1);
			scanf("%f", &X[i][j]);
		}
	}
	return;
}

void Multiply_matrix(float(*X)[N], float(*Y)[N], float(*B)[N], int n) {
	int i = 0, j = 0, k = 0;
	for (i = 0; i < n; i++) {
		for (j = 0; j < n; j++) {
			B[i][j] = 0;
			for (k = 0; k < n; k++) {
				B[i][j] += X[i][k] * Y[k][j];//Bを初期化しないと計算が余分;
			}
		}
	}
	return;
}

void Power_matrix(float(*X)[N], float(**Y)[N], int n, int k)//*Y=k乗としたい
{

	int i;
	float B[N][N] = { { 0 } }, C[N][N] = { { 0 } };
	float (*x)[N], (*y)[N], (*tmp)[N];
	if (k == 0 || k == 1) {
		*Y = X;

	}
	Multiply_matrix(X, X, B, n);
	x = B;
	y = C;
	for (i = 2; i < k; i++) {
		Multiply_matrix(X, x, y, n);
		tmp = x;
		x = y;
		y = tmp;
	}
	tmp = x;
	x = y;
	y = tmp;
	*Y = y;

}
void Print_matrix(float(*Y)[N], int n) {
	int i = 0, j = 0;
	for (i = 0; i < n; i++) {
		for (j = 0; j < n; j++) {
			printf("[%d][%d]=%f\n", i + 1, j + 1, Y[i][j]);
		}
	}
	return;
}

int main(void) {
	float X[N][N] = { { 0 } }, (*Y)[N];//初期化しないと行列計算の時おかしくなる
	int n = 0, k = 0;
	printf("n(0<n<=5 nは整数)を決めてください。n=");
	scanf("%d", &n);
	if (n > 5 || n <= 0) {
		printf("エラー:n<=5となるnを入力してください\n");
		return (-1);
	}
	Input_matrix(X, n);//行列の入力
	printf("k乗なるk(kは自然数)を入力してください\n[行][列]\n");
	scanf("%d", &k);
	if (k <= 0) {
		printf("エラー:kは自然数です");
		return (-1);
	}
	Power_matrix(X, &Y, n, k);//行列の計算
	Print_matrix(Y, n);
	return 0;
}

Re: 前の続きです・・・行列

Posted: 2012年5月16日(水) 20:57
by かずま
れお さんが書きました: おそらくPower_matrixの中身だけかえればいけるとおもうのですが・・・
float B[N][N] = { { 0 } }, C[N][N] = { { 0 } }; の float の前に static
*Y = X; の後に return;

Re: 前の続きです・・・行列

Posted: 2012年5月16日(水) 21:04
by れお
いけました!!
ほんとありがとうございます><返信も早くて助かります^^
staticなんてつかったことなかったです・・・
今からちょっと調べてきます。

ちなみに48~51行って、どうなっているんですかね?ここはちょっと友達がやったので意味がわかってません。
for文で tmp = x;
x = y;
y = tmp;
としたあとに、
tmp = x;
x = y;
y = tmp;
*Y = y;
をすると、yの値などがかわってしまうとおもうのですが・・・


調べたけどわかりませんでした。
Power_matrixは1回しかよびだされませんよね?staticにしたらなんでいけるようになるんでしょう??><

Re: 前の続きです・・・行列

Posted: 2012年5月16日(水) 22:55
by かずま
れお さんが書きました:Power_matrixは1回しかよびだされませんよね?staticにしたらなんでいけるようになるんでしょう??><
関数の外部で宣言された変数は、プログラムの開始から終了までの寿命があります。
関数の内部で宣言された変数は、その関数の実行の開始から終了までの寿命があります。
Power_matrix() から main() に戻ると、B も C も無くなってしまうのです。
実際には無くなるというよりも、他のところで使われて中身が変わってしまうといっていいでしょう。
今回の場合、Print_matrix() やそこから呼び出された printf() が使用しています。
static をつけると、変数の寿命がプログラムの開始から終了までとなります。
だから、Power_matrix() から main() に戻っても存在し続け、そこを指している
main() のポインタ Y で B または C の値を参照できるのです。

48~51行目は、x と y の値を交換して、y を main() の ポインタ Y に代入しています。
この 4行は *Y = x; と書いても同じです。というか、そう書くべきです。

44~46行目も、x と y の値を交換していますが、これは
Multiply_matrix(X, B, C, n); と
Multiply_matrix(X, C, B, n); を交互に実行するためです。
for 文に入る前も、for文を抜けた後も、B または C のうち、
x が指している方に結果が入っています。

Re: 前の続きです・・・行列

Posted: 2012年5月16日(水) 23:15
by れお
なるほど。。。
じゃあメイン関数以外の関数では全てにstaticをつけといても問題ないのですか?(ループを回すi,jなどはのぞいて。これも変数の文字をかえたらstaticをつけても別に問題ないですよね?)

後半は理解できました^^
ほんとに感謝します!!


宿題が出るたびに知らないことがまだまだあってまだCの1割も理解してないような気がしてこわいですww

Re: 前の続きです・・・行列

Posted: 2012年5月17日(木) 01:19
by かずま
れお さんが書きました:じゃあメイン関数以外の関数では全てにstaticをつけといても問題ないのですか?
何度も呼び出すと、前の結果が壊れてしまいます。
だから、再帰呼び出しやマルチスレッドで正しい結果が出ないことがあります。

例えば、次の次のプログラムはどんな結果を表示すると思いますか?

コード:

    float (*Y)[N}, (*Z)[N};
        :
    Power_matrix(X, &Y, n, 2);
    Power_matrix(X, &Z, n, 4);
    printf("X^2:\n"); Print_matrix(Y, n);
    printf("X^4:\n"); Print_matrix(Z, n);

Re: 前の続きです・・・行列

Posted: 2012年5月24日(木) 20:40
by れお
なるほど!
後でやったほうが上書きされてしまうのですね!!

つまりその例においては
Power_matrix(X, &Y, n, 2);
  printf("X^2:\n"); Print_matrix(Y, n);
Power_matrix(X, &Z, n, 4);
printf("X^4:\n"); Print_matrix(Z, n);
こうすれば問題ないのですね?^^

Re: 前の続きです・・・行列

Posted: 2012年5月25日(金) 15:38
by みけCAT
なぜ私の最新のコードはスルーされている(ように見える)のでしょうか?
なにもコメントがついていないのですが・・・。