n次の正則行列から、逆行列を求めるプログラムを作ってみたくなり、コードを書いたのですが、うまくいきません
テストとして、3次の単位行列の逆行列を求めようとしたプログラムを以下のように作りました
デバッガを使って、間違っているところの検討はつけているのですが、
168行目? この部分のinv[0][0]がすでに予想と違う値(ー3)になっているのですが、
この右辺の各オペランドは正常な値をとっていることがわかりました
なぜ、値が異なってしまうのでしょうか?
原因がわからなくて困っています
力を貸してもらえませんか
問題は関数⑧です
#include <stdio.h>
#define NUM 3
int Judge1=0;
int Judge2=0;
void mat_express1(int a[NUM][NUM]){ //NUM次正方行列を表示する 関数①
for(int i=0;i<NUM;i++){
for(int j=0;j<NUM;j++)
printf("%3d",a[i][j]);
printf("\n");
};
}
void mat_tri1(int b[][NUM]){ //NUM次正方行列を行基本変形して、上三角行列にする 関数②
int i,j,k; int mul;
Judge1=0;
for (i=0;i<NUM;i++)
{
mul=b[i][i];//対角要素mulをi列掃き出しの要とする
if(mul==0)//もし、対角要素mulが0なら上三角化強制終了
{
Judge1=1;//行列式の値が0であることのフラグを立てる(関数④につなげる)
break;
};
for(k=i+1;k<NUM;k++)
{
int c=b[k][i];
for(j=0;j<NUM;j++)
{
double sub=b[k][j]-c*b[i][j]/mul;
b[k][j]-=c*b[i][j]/mul;
if(b[k][j]<sub)//もし要素が整数にならないなら、上三角化を諦める
{
printf("正しくない");
break;
};
};
};
};
} //終了
void mat_tri2(int b[][NUM-1]){//NUM-1次正方行列の上三角化(関数②と同じ) 関数③
int i,j,k; int mul;
Judge2=0;
for (i=0;i<NUM-1;i++)
{
mul=b[i][i];
if(mul==0)
{
Judge2=1;
break;
};
for(k=i+1;k<NUM-1;k++)
{
int c=b[k][i];
for(j=0;j<NUM-1;j++)
{
double sub=b[k][j]-c*b[i][j]/mul;
b[k][j]-=c*b[i][j]/mul;
if(b[k][j]<sub)
{
printf("正しくない");
break;
};
};
};
};
} //終了
int det1(int va[][NUM]){ //NUM次正方行列の行列式の値を求める 関数④
int seki=va[0][0];
if(Judge1==0)
{
mat_tri1(va);
int i;
for(i=1;i<NUM;i++)
seki*=va[i][i];//上三角化した行列の対角要素をすべてかける
}
if(Judge1==0)
return(seki);
else
return(0);
}
int det2(int va[][NUM-1]){ //NUM-1次正方行列の行列式の値を求める(関数④と同じ) 関数⑤
int seki=va[0][0];
if(Judge2==0)
{
mat_tri2(va);
int i;
for(i=0;i<NUM-1;i++)
seki*=va[i][i];
};
if(Judge2==0)
return(seki);
else
return(0);
}
void kurinuki(int origin[][NUM],int small[][NUM-1],int i,int j){ //行列originの i行j列をくり抜いた行列smallを作る 関数⑥
int n,m;
for(n=0;n<i-1;n++)
{
for(m=0;m<j-1;m++)
{
small[n][m]=origin[n][m];
};
for(m=j;m<NUM;m++)
{
small[n][m-1]=origin[n][m];
};
};
for(n=i;n<NUM;n++)
{
for(m=0;m<j-1;m++)
{
small[n-1][m]=origin[n][m];
}
for(m=j;m<NUM;m++)
{
small[n-1][m-1]=origin[n][m];
}
};
}
void mat_copy(int origin[][NUM],int copy[][NUM]){//行列originを行列copyに写す 関数⑦
for(int i=0;i<NUM;i++)
for(int j=0;j<NUM;j++)
copy[i][j]=origin[i][j];
}
void inv_mat(int origin[][NUM],int inv[][NUM]){ //行列originの逆行列invを得る 関数⑧
int small[NUM-1][NUM-1];
int det[NUM][NUM];
int k,s;
int copy[NUM][NUM];
mat_copy(origin,copy);
for(k=0;k<NUM;k++)
{
for(s=0;s<NUM;s++)
{
mat_copy(copy,origin); //上三角化されたoriginの復元
kurinuki(origin,small,k+1,s+1); //originのk+1行s+1列をくり抜いてsmall行列を作る
det[k][s]=det2(small); //smallの行列式を行列detの(k,s)成分とする
inv[s][k]=((-1)^(k+s+2))*(det[k][s])/(det1(origin)); //逆行列の各要素の計算
};
};
}
int main(void){
int vc[NUM][NUM]={1,0,0,
0,1,0,
0,0,1};
int gyaku[NUM][NUM];
mat_express1(vc);
printf("\n");
inv_mat(vc,gyaku);
mat_express1(gyaku);
return 0;
}