ページ 11

掃出し法のプログラムについて

Posted: 2013年4月27日(土) 12:56
by 光坂
[1] 質問文
 [1.1] 掃出し法をつかって逆行列を求めるプログラム
 [1.2]
#include <stdio.h>
#include <math.h>
#define N 4
#define N1 8
#define EPSILON 1.0E-5
#define TRUE 1
#define FALSE 0

float a[N][N1]={{1.0,0.75,0.0,-0.5,1.0,0.0,0.0,0.0},
{0.0,-0.25,0.0,0.5,0.0,1.0,0.0,0.0},
{0.0,0.75,0.0,-0.5,0.0,0.0,1.0,0.0},
{-2.0,-1.5,-1.0,1.0,0.0,0.0,0.0,1.0}};
float det;
int sw;
void main()
{
int i,j;
void sweep();
printf("\n\n===== 元の行列 ====\n\n");
for(i=0;i<N;i++)
{
printf("%d:",i+1);
for(j=0;j<N;j++)
printf(" %10.4f",a[j]);
printf("\n");
}
printf("\n\n");
sw=TRUE;

sweep(&sw);

if(sw==TRUE)
{
printf("\n\n==== 逆行列 ====\n\n");
for(i=0;i<N;i++)
{
printf(" %d;",i+1);
for(j=N;i<N1;j++) printf(" %d10.4f ",a[j]);
printf("\n");
}
printf("\n 行列式=%8.4f \n",det);
}
else
{
printf("\n逆行列は求まりませんでした!\n");
}
}

void swap(wk1,wk2)
float *wk1,*wk2;
{
float w;
w=*wk1; *wk1=*wk2;*wk2=w;
}

void sweep(sw)
int *sw;
{
int i,j,k,ik;
float ak,aik,p;

det=1.0;
p=1.0;
for(k=0;k<N;k++)
{
ak=a[k][k];
if(fabs(ak)<=EPSILON)
{
ik=k+1;
while((ik<N) && (fabs(a[ik][k])<EPSILON)) ik++;
if(ik<N)
{
for(j=k;j<N1;j++){ swap(&a[k][j],&a[ik][j]);}
ak=a[k][k];
p=-p;
}
if(ik>=N)
{
printf(" ピボットが零です ! \n");
*sw=FALSE;
goto owari;
}
}
det=det*ak;
for(j=k;j<N1;j++) a[k][j]=a[k][j]/ak;
for(i=0;i<N;i++)
{
if(i!=k)
{
aik=a[k];
for(j=k;j<N1;j++) a[j]=a[j]-aik*a[k][j];
}
}
}
det=p*det;
owari:;
}


 [1.3] 教科書のプログラムをそのまま入力してみましたが、コンパイルエラーは出ないのですが、うまく動作しません
 [1.4] どこを修正すればいいか教えていただけると助かります

[2] 環境  
 [2.1] OS : Windows7
 [2.2] コンパイラ名 : gcc

[3] 教科書の丸写しの間違いは確認したのでないと思います
 ・基礎は理解しています

Re: 質問の変更

Posted: 2013年4月27日(土) 13:31
by 光坂
[1] 質問文
 [1.1] 掃出し法をつかって逆行列を求めるプログラム
 [1.2]
code
#include <stdio.h>
#include <math.h>
#define N 4
#define N1 8
#define EPSILON 1.0E-5
#define TRUE 1
#define FALSE 0

float a[N][N1]={{1.0,0.75,0.0,-0.5,1.0,0.0,0.0,0.0},
{0.0,-0.25,0.0,0.5,0.0,1.0,0.0,0.0},
{0.0,0.75,0.0,-0.5,0.0,0.0,1.0,0.0},
{-2.0,-1.5,-1.0,1.0,0.0,0.0,0.0,1.0}};
float det;
int sw;
void main()
{
int i,j;
void sweep();
printf("\n\n===== 元の行列 ====\n\n");
for(i=0;i<N;i++)
{
printf("%d:",i+1);
for(j=0;j<N;j++)
printf(" %10.4f",a[j]);
printf("\n");
}
printf("\n\n");
sw=TRUE;

sweep(&sw);

if(sw==TRUE)
{
printf("\n\n==== 逆行列 ====\n\n");
for(i=0;i<N;i++)
{
printf(" %d;",i+1);
for(j=N;i<N1;j++) printf(" %d10.4f ",a[j]);
printf("\n");
}
printf("\n 行列式=%8.4f \n",det);
}
else
{
printf("\n逆行列は求まりませんでした!\n");
}
}

void swap(wk1,wk2)
float *wk1,*wk2;
{
float w;
w=*wk1; *wk1=*wk2;*wk2=w;
}

void sweep(sw)
int *sw;
{
int i,j,k,ik;
float ak,aik,p;

det=1.0;
p=1.0;
for(k=0;k<N;k++)
{
ak=a[k][k];
if(fabs(ak)<=EPSILON)
{
ik=k+1;
while((ik<N) && (fabs(a[ik][k])<EPSILON)) ik++;
if(ik<N)
{
for(j=k;j<N1;j++){ swap(&a[k][j],&a[ik][j]);}
ak=a[k][k];
p=-p;
}
if(ik>=N)
{
printf(" ピボットが零です ! \n");
*sw=FALSE;
goto owari;
}
}
det=det*ak;
for(j=k;j<N1;j++) a[k][j]=a[k][j]/ak;
for(i=0;i<N;i++)
{
if(i!=k)
{
aik=a[k];
for(j=k;j<N1;j++) a[j]=a[j]-aik*a[k][j];
}
}
}
det=p*det;
owari:;
}
/code

 [1.3] 教科書のプログラムをそのまま入力してみましたが、コンパイルエラーは出ないのですが、うまく動作しません
 [1.4] どこを修正すればいいか教えていただけると助かります

[2] 環境  
 [2.1] OS : Windows7
 [2.2] コンパイラ名 : gcc

[3] 教科書の丸写しの間違いは確認したのでないと思います
 ・基礎は理解しています

再質問させていただきます

Posted: 2013年4月27日(土) 13:33
by 光坂
すいません

Re: 掃出し法のプログラムについて

Posted: 2013年4月27日(土) 13:34
by box
写し間違いはないとのことですが、
光坂 さんが書きました:

コード:

			for(j=N;i<N1;j++) printf(" %d10.4f ",a[i][j]);
本当に i < N1 でいいのかどうか
%d10.4f という書式文字列は本当に正しいかどうか
とりあえずこの2点を確認してみてください。