###前提・実現したいこと
Cで行列のランク計算をするプログラムを作っています。
プログラムの流れは、
1.行列の行数(lnum)、列数(cnum)を入力
2.行列の各成分を入力、格納。
3.行列の走査(matsearch)を行う。
走査範囲は初めは1列目の全行であるとする。
1列目から順に
特定の列の走査範囲内の要素をを上から順に確認
→すべて0 ⇒ 走査範囲はそのままで次の列に
→上端が非0かつ上端以外はすべて0 ⇒ 走査範囲を一つ縮める(元の走査範囲から上端の行を抜いたもの)。そして走査範囲は次の列へ
→上端以外に非0が存在
⇒ その列が基本変形対象範囲最重要列J₀
かつ
その走査範囲の上端の行は基本変形対象範囲開始行I₀。
for行ループ → break
for列ループ → break
matsearch → 終了
最終的に…matsearchの返却値は
①J=cnumですべてその列の成分が0
→ -2
②(I₀,J₀)=0かつbreak
→ I₀
③(I₀,J₀)≠0かつbreak
→ -1
4.行基本変形
①:
rank計算へ
②:
(I, J₀)成分のうち、I₀≦I≦lnumの範囲で
非0となっている成分について考える。
このような成分のうち、最小行番号をもつ成分の行番号
をI₁とする。(I₀<I₁≦lnum)
2-2-1.1:(I₁,J)成分でI₁行成分をすべて割る。
2-2-1.2:(I₀,J)成分に
「(I₀,J)成分 + (I₁,J)成分」
の演算結果を代入する。
2-2-1.3:
(I,J)成分に(I>I₀)
「(I,J)成分 -{(I,J)成分*(I₀,J)}」
の演算結果を代入する。
そのまま③へ
③:
操作2-1
2-1.1:(I₀ , J₀)成分でI₀行成分をすべて割る。
2-1.2:(I,J)成分に(I>I₀)
「(I,J)成分 -{(I,J)成分*(I₀,J)}」
の演算結果を代入する。
という手順を踏んで行基本変形を行う予定だったのですが、この手順通りに操作がいかないです。
どうかよろしくおねがいいいたします。
###発生している問題・エラーメッセージ
計算過程でループが終了せずどこが間違っているのかがわからないです。
###該当のソースコード
#include <stdio.h> #define NA 7 #define NB 3 #define PLUS 0 #define MINUS 1 #define ERROR_R 1.000000e-15 int zerojudgef(double a) { return ((a < ERROR_R) & (a > (-1)*ERROR_R) ? 0 : 1); } int matsearchf(double mat[][NA][NA], int lnum, int cnum, int keylinenum, int keycolumnnum, int rank) /* keylinenum : the number of line that is the start point of elementary row operation. Exactly, in the column of key-column number, and below the line of the start line of elemntary row operation ,there may exists the element that is not zero which has the smallest number of line. The line number of such elements is defined as keylinenum. That is, if the start line of elementary row operation is not the exactly defined keyline number, the start line of elementray row operation is linebreak. keycolumnnum : the number of column that is the key-column of elementary row op ertion. */ { int i, j; int linebreak = 0; for(j=0; j<cnum; j++){ int k = 0; int notzero = 0; int keynum_for_count = 0; for(i=linebreak; i<lnum; i++){ if(zerojudgef(mat[0][i][j])){ notzero++; }/*for-for-if*/ }/*for-for*/ /*Finding out the key-line number In the column of key-column number, and below the line of key-line number, there may exists the element that is not zero which has the smallest number of line. The line number of such elements is defined as keylinenum, and in this function, for the purpose of counting the key-line number, a variable 'keynum_for_count' is defined. */ do{ keynum_for_count = (zerojudgef(mat[0][k][j]) != 0 ? k : -1);//ここは最悪k+linebreakでもok k++; }while( (keynum_for_count < 0) & (k != (NA-1) ) );//matのイランとこは全部0で初期化が条件 if(zerojudgef(notzero)){/*There exist at least one element that is not equal to zero.*/ if(zerojudgef(mat[0][linebreak][j])){/*The top elements in the scope of line-searching is not equal to zero.*/ if(notzero > 1){/*There exists not-zero elemnet at the top of the scope of line searching, and exists not-zero elements below the elements at the top. break roop*/ keylinenum = keynum_for_count; keycolumnnum = j; return -1; break; }else{ /*There exists not-zero element only at the top of the searching range, and elements below it is all equal to zero. continue roop*/ linebreak++; }/*for-if-if-if*/ }else{/*The top elements in the scope of line-searching is equal to zero, but there exist at least one elements that is not equal to zero. break roop*/ keylinenum = keynum_for_count; keycolumnnum = j; return linebreak; break; }/*for-if-if*/ }else{/*There exist only elements that is equal to zero. continue roop*/ }/*for-if*/ }/*for*/ rank = linebreak; return -2; /*Finally, the result is classified into 3 types. 1:All the elemnets in the last column of the scope is equal to zero. output = -2 2:The (keylinenum, keycolumnnum) elemnet is equal to zero. output = linebreak 3:The (keylinenum, keycolumnnum) elemnet is not equal to zero. output = -1 */ } void divf(int divdo, int divdonel, int cnum, double mat[][NA][NA]) { /* divdo :割る数の要素の列番号 divdonel :割られる数の要素が存在する行番号 cnum :割り算実行される行の列数 */ double divisor = mat[0][divdonel][divdo]; int i; for(i=0; i<cnum; i++){ mat[0][divdonel][i] /= divisor; } /**/ int line, column; puts("divf"); printf("\n"); for(line=0; line<NA; line++){ printf("|"); for(column=0; column<NA; column++){ printf("%5.2f", mat[0][line][column]); } printf(" |\n"); } printf("\n\n"); /**/ } void subtraf(int p, int q, int r, int cnum, double mat[][NA][NA], double coeff) { /* This function operates the line p ± the line q. Judge by whether r = 0 or 1 -r=0→addition+ -r=1→subtractionー cnum = The total number of line coeff = the coefficient of the number that subtacts any numbers */ int pm = (r == 1 ? (-1) : 1); int i; for(i=0; i<cnum; i++){ mat[0][p][i] += (coeff * pm * mat[0][q][i]); } /**/ int line, column; puts("subtraf"); printf("\n"); for(line=0; line<NA; line++){ printf("|"); for(column=0; column<NA; column++){ printf("%5.2f", mat[0][line][column]); } printf(" |\n"); } printf("\n\n"); /**/ } void erowoperatef(double mat[][NA][NA], int lnum, int cnum, int keylinenum, int keycolumnnum) { int rank = 0; int i, j, k; int breakjudge = 0; for(i=0; i<NA; i++){ k = ( ( matsearchf(mat, lnum, cnum, keylinenum, keycolumnnum, rank) < 0 ) ? matsearchf(mat, lnum, cnum, keylinenum, keycolumnnum, rank) : 1 ); switch(k){ case 1:{ divf(keycolumnnum, keylinenum, cnum, mat); subtraf( matsearchf(mat, lnum, cnum, keylinenum, keycolumnnum, rank), keylinenum, PLUS, cnum, mat, 1); }/*for-switch-case0*/ case -1:{ divf(keycolumnnum, keylinenum, cnum, mat); if(i = keylinenum){ }else{ for(j=0; j<lnum; j++){ subtraf( j, keylinenum, MINUS, cnum, mat , mat[0][j][keycolumnnum]); }/*for-switch-case-1-if-for*/ }/*for-switch-case-1-if*/ break; }/*for-switch-case1*/ case -2:{ breakjudge = 1; break; }/*for-switch-case-1*/ }/*switch*/ if(breakjudge == 1){ break; }/*for-if*/ }/*for*/ } int rankcaloperatef(double mat[][NA][NA], int lnum, int cnum) { int keylinenum = 0; int keycolumnnum = 0; erowoperatef(mat, lnum, cnum, keylinenum, keycolumnnum); int rank = 0; int empty = matsearchf(mat, lnum, cnum, keylinenum, keycolumnnum, rank); return rank; } int main(void) { double mat[NB][NA][NA] = {}; int lnum, cnum; /*mat[kind of matrix][line number][column number] */ puts("\nWe will calculate the rank of a matrix.\nPlease enter the scale of matrix."); printf("The number of lines (under %d) = ", NA); scanf("%d", &lnum); printf("The number of columns (under %d) = ", NA); scanf("%d", &cnum); puts("Please enter the elements of the matrix."); puts("'mat[i][j]' represents the (i,j) elements of the matrix."); int i, j; for(i=0; i<lnum; i++){ for(j=0; j<cnum; j++){ printf("mat[%d][%d] = ", i+1, j+1); scanf("%lf", &mat[0][i][j]); mat[1][i][j] = mat[0][i][j]; } } /*mat[1]にはもともと行列が保存される。*/ int Rank = rankcaloperatef(mat, lnum, cnum); int r; for(r=0; r<2; r++){ printf("\n"); for(i=0; i<lnum; i++){ printf("|"); for(j=0; j<cnum; j++){ printf("%5.f", mat[r][i][j]); } printf(" |\n"); } printf("\n\n"); } printf("\nThe rank of this matrix is %d.\n", Rank); return 0; }
###試したこと
上のソースコードのなかで、2つの/**/で挟まれたprintf …の部分は演算過程を見るために付け加えたものです。いくつかのデバッグは自己解決できたのですが、これに関してはわからないです。
又、初めのアルゴリズムでは欠陥があったので、少し変えて作り直しました。
回答2件
あなたの回答
tips
プレビュー