. Cプログラミング (2014) . 第5回 − 宿題1の解説と演習1 − 松田七美男 2014 年 10 月 23 日 . 宿題 1:概要 . ガウスの消去法の確認 . 3 次の Hilbert 行列(係数が hij = 1/(i + j − 1))を係数行列 とする 3 元連立一次方程式を Gauss の消去法を用いて解き .なさい. 定数 bi は 1 ≤ bi ≤ 10 の整数となるように,疑似乱数発 生関数 rand() を用いて main 関数内で定義しなさい. rand() を使うには,初期化関数 srand() を適当な整数 seed を引数に srand(seed) と呼び出す必要がありま す.この seed には,各自の学籍番号を用いなさい. 例) 13YB034* ⇒ seed=34 Ax が b に等しいことを確かめる検算結果も表示しな さい. . 個人毎の方程式の定義 係数行列 A と定数ベクター b の要素を乱数を用いて定義 する. #define N 3 #define SEED 300 ... srand(SEED); for (i = 0; i < N; i++) { b[i] = rand() % 10 + 1; for (j = 0; i < N; j++) { A[N*i + j] = 1.0/(i + j +1); } } ... . ソース例 #include "lineq.h" #define N 3 #define SEED 300 copy_mat(A, Ai, N, N); print_mat("A =", A, N, N); print_vec("b =", b, N); mat_gauss(A, b, x, N); print_vec("x =", x, N); calc_ax(Ai, x, Ax, N); print_vec("Ax = b?", Ax, N); int main(int argc, char *argv[]) { int i, j; Mat A, Ai; Vec b, x, Ax; srand(SEED); A = calloc( N*N, sizeof(double)); Ai = calloc( N*N, sizeof(double)); b = calloc( N, sizeof(double)); x = calloc( N, sizeof(double)); Ax = calloc( N, sizeof(double)); for (i = 0; i < N; i++) { b[i] = rand() % 10 + 1; for (j = 0; j < N; j++) { A[N*i+j] = 1.0/(i+j+1); } } . free(A); free(Ai); free(b); free(x); free(Ax); return 0; } . ソース例 #include "lineq.h" #define N 3 #define SEED 300 copy_mat(A, Ai, N, N); print_mat("A =", A, N, N); print_vec("b =", b, N); mat_gauss(A, b, x, N); print_vec("x =", x, N); calc_ax(Ai, x, Ax, N); print_vec("Ax = b?", Ax, N); int main(int argc, char *argv[]) { int i, j; Mat A, Ai; Vec b, x, Ax; srand(SEED); 乱数の初期化 A = calloc( N*N, sizeof(double)); Ai = calloc( N*N, sizeof(double)); b = calloc( N, sizeof(double)); x = calloc( N, sizeof(double)); Ax = calloc( N, sizeof(double)); for (i = 0; i < N; i++) { b[i] = rand() % 10 + 1; for (j = 0; j < N; j++) { A[N*i+j] = 1.0/(i+j+1); } } . free(A); free(Ai); free(b); free(x); free(Ax); return 0; } . ソース例 #include "lineq.h" #define N 3 #define SEED 300 copy_mat(A, Ai, N, N); print_mat("A =", A, N, N); print_vec("b =", b, N); mat_gauss(A, b, x, N); print_vec("x =", x, N); calc_ax(Ai, x, Ax, N); print_vec("Ax = b?", Ax, N); int main(int argc, char *argv[]) { int i, j; Mat A, Ai; Vec b, x, Ax; srand(SEED); 乱数の初期化 A = calloc( N*N, sizeof(double)); Ai = calloc( N*N, sizeof(double)); b = calloc( N, sizeof(double)); x = calloc( N, sizeof(double)); Ax = calloc( N, sizeof(double)); free(A); free(Ai); free(b); free(x); free(Ax); return 0; } for (i = 0; i < N; i++) { b[i] = rand() % 10 + 1; for (j = 0; j < N; j++) { A[N*i+j] = 1.0/(i+j+1); aij } i,j が 0 から始まっている点に注意 } . . ソース例 #include "lineq.h" #define N 3 #define SEED 300 copy_mat(A, Ai, N, N); print_mat("A =", A, N, N); print_vec("b =", b, N); ガウスの消去法の呼出し mat_gauss(A, b, x, N); int main(int argc, char *argv[]) print_vec("x =", x, N); { calc_ax(Ai, x, Ax, N); int i, j; print_vec("Ax = b?", Ax, N); Mat A, Ai; Vec b, x, Ax; free(A); free(Ai); srand(SEED); 乱数の初期化 free(b); A = calloc( N*N, sizeof(double)); free(x); Ai = calloc( N*N, sizeof(double)); free(Ax); b = calloc( N, sizeof(double)); x = calloc( N, sizeof(double)); return 0; Ax = calloc( N, sizeof(double)); } for (i = 0; i < N; i++) { b[i] = rand() % 10 + 1; for (j = 0; j < N; j++) { A[N*i+j] = 1.0/(i+j+1); aij } i,j が 0 から始まっている点に注意 } . . 演習 1:課題 . LU . 分解法により逆行列を得る関数 LU 分解去を用いて,行列 A の逆行列 X = A−1 を .求める関数 inv mat を作成しなさい. 宣言:inv mat(Mat A, int N) テストプログラム lineq invpascal.c を作成して,5 次の Pascal 行列(Pij = Pi−1,j + Pi,j−1 , P1,j = Pi,1 = 1) の逆行列を求めなさい. . 逆行列 . i 番目 . とすると, z}|{ bi = (0, · · · , 1 , · · · , 0)T xi : Axi = bi の解 . 逆行列 . i 番目 . z}|{ bi = (0, · · · , 1 , · · · , 0)T xi : Axi = bi の解 とすると,逆行列は以下のように計算される. ] [ A−1 = A−1 I = A−1 b1 , b2 , · · · , bn [ ] = A−1 b1 , A−1 b2 , · · · , A−1 bn [ ] = x1 , x2 , · · · , xn . 逆行列 . i 番目 . z}|{ bi = (0, · · · , 1 , · · · , 0)T xi : Axi = bi の解 とすると,逆行列は以下のように計算される. ] [ A−1 = A−1 I = A−1 b1 , b2 , · · · , bn [ ] = A−1 b1 , A−1 b2 , · · · , A−1 bn [ ] = x1 , x2 , · · · , xn bi 毎に xi を計算し,それらを順番に並べればよい. . 演習 1:実行画面 . テストプログラム inv の実行画面 . $ ./ex2014A-1 A = 1 1 1 2 1 3 1 4 1 5 1 3 6 10 15 1 4 10 20 35 1 5 15 35 70 X = 5 -10 10 -5 1 -10 30 -35 19 -4 10 -35 46 -27 6 -5 19 -27 17 -4 1 -4 6 -4 1 AX = I? 1 0 0 0 . 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 . 演習 1:実行画面 . テストプログラム inv の実行画面 . $ ./ex2014A-1 A = 1 1 1 2 1 3 1 4 1 5 1 3 6 10 15 1 4 10 20 35 1 5 15 35 70 X = 5 -10 10 -5 1 -10 30 -35 19 -4 10 -35 46 -27 6 -5 19 -27 17 -4 1 -4 6 -4 1 AX = I? 1 0 0 0 . 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 単位行列 0 0 1 0 0 . 演習課題提出に関する注意 Waseda-net Web メールサービスを用いて提 出しなさい. 宛先は [email protected] 件名には,学生番号(英数半角),名前,演習1をこの 順に記述しなさい. 例)1Y13B999,△○ ×□,演習 1 〆切は,10 月 23 日 10:30 送信控えの保存を忘れずに ソース(inv mat.c と lineq invmat.c)と実行 結果の両方が必要.添付不可. ソースには空白を挿入したり,字下げをほど こすなど読みやすくなる工夫をしなさい.
© Copyright 2024 ExpyDoc