Download presentation
Presentation is loading. Please wait.
1
コンピュータ基礎実験 第1 0回 コンピュータープログラミン グ ( C 言語)(8) 1.乱数(復習) 2.配列とその利用
2
乱数(復習) ランダムに変化する数を生成する関数「乱 数」 C言語の乱数:「 rand() 」関数 #include が必要 srand(s): 乱数系列の初期化関数( s は int 型整数) srand(s) を実行した時点から、 s に応じた乱数の系列が始まる s が同じなら同じ乱数の列が得られる 「 srand((unsigned int)time(NULL)); 」を使うと s をいちいち入力 する手間が省ける( time() 関数を使うには「 #include 」が必要) #include int main(void) { ‥‥ srand((unsigned int)time(NULL)); ‥‥ rn=rand(); ‥‥ }
3
3 前回課題 EX9-7 0 から 9 までの乱数を N 個発生させ,それぞれの数字が出た回数およ び確率を出力するプログラムを作成せよ。 とくに N=100 と 10000 の場合について, 確率のバラツキはどちらが小さいか確認せよ。 ( EX9-7.c) 0 から 9 までの乱数は、「 rand()%10 」で発生させる 0 ~ 9 ごとの発生回数はメンバー数 10 の int 型配列に記録する int ev[10]={0,0,0,0,0,0,0,0,0,0}; 0 で初期化しておく 配列を使わずに、 ev0, ev1, ev2 ‥‥でもよいが、出た乱数毎に switch, case 文で場合分けすることが必要 回数のカウントアップには、「 ev[rn]++; 」を実行すればよい i++; ⇔ i+=1; ⇔ i=i+1; ← 全部同じ結果
4
4 前回課題 EX9-7 0 から 9 までの乱数を N 個発生させ,それぞれの数字が出た回数およ び確率を出力するプログラムを作成せよ。 とくに N=100 と 10000 の場合について, 確率のバラツキはどちらが小さいか確認せよ。 ( EX9-7.c) #include int main(void) { int i,n_ev,rn; int ev[10]={0,0,0,0,0,0,0,0,0,0}; srand((unsigned int)time(NULL)); printf("Input number of events: "); scanf("%d",&n_ev); for(i=0; i<n_ev; i++){ rn=rand()%10; ev[rn]++; } for(i=0; i<10; i++){ printf("%d は %d 回、確率は %f で す \n",i,ev[i],(float)ev[i]/n_ev); } return 0; }
5
配列とその利用 乱数発生回数のカウントアップに配列を利用 しましたが、それ以外に配列を利用できない でしょうか? 「確率のバラツキ」をもとめるには、平均と標 準偏差が必要⇒カウントアップに用いた配列を 利用しては! 「数の組」⇒ベクトル、行列の計算に利用でき ないか? ベクトル、行列⇒連立方程式を解くことに利用 できないか?
6
配列を使った平均、標準偏差計 算 0 ~ 9 の出現回数が ev[0] ~ ev[9] に記録されて いる。これを利用して、出現回数と確率の平 均値とバラツキを計算しよう。 平均値: 標準偏差(バラツキの指標) :
7
7 例題 EX10-1 0 から 9 までの乱数を N 個発生させ,それぞれの数字が出た回数の平 均値と標準偏差を計算せよ。 とくに N=100 と 10000 の場合につい て平均値と標準偏差(バラツキ)を計算せよ。 ( EX10-1.c) #include int main(void) { int i,n,rn; float m=0,s=0; int ev[10]={0,0,0,0,0,0,0,0,0,0}; srand((unsigned int)time(NULL)); printf("Input number of events: "); scanf("%d",&n); for(i=0; i<n; i++){ rn=rand()%10; ev[rn]++; } for(i=0; i<10; i++){ m+=(float)ev[i]; s+=(float)ev[i]*ev[i]; } m/=10; /* m=m/10; と同じ意味 */ s-=(10*m*m); s/=(10-1); s=sqrt(s); printf(”" 平均値 =%f 標準偏差 =%f\n",m,s); return 0; } *sqrt() を使うので、「 #include 」 が必要 平均値が毎回ぴったり同じなのははぜ?
8
課題 EX10-2 0 から 9 までの乱数を N 個発生させ,それぞれの数字がでた確率の平 均値と標準偏差(バラツキ)を計算せよ。 とくに N=100 と 10000 の場合について標準偏差の大きさを比較せよ。 ( EX10-2.c)
9
9 例題 EX10-3 一様な確率分布の乱数を複数個足した数は、正規分布(ガウス分 布)に従うことが知られている。いま、 0 ~ 9 の間に一様に分布す る整数の乱数を 10 個足し 5 で割った整数を X とする。 X を N 個発生さ せ、それぞれの数字が出た回数および確率を出力するプログラムを 作成せよ。 ( EX10-3.c) 結果の確率分布をエクセルでグラフにせよ。 0 ~ 9 の乱数は「 rand()%10 」で生成できそう 一個の X を発生させるのに、10回ループする「 for 文」で、 「 rand() 」で生成した乱数を足していけばよい 上のループを N 回繰り返せばよい 発生回数のカウントアップは EX9-7.c のやり方が利用できそう X の範囲は 0 ~ 18 の整数になる * 画面出力をファイルに保存する方法は、 http://www.tuat.ac.jp/~muroo/computer-tips.html を参照 $./EX10-3.exe 1> result.dat とすると、 result.dat に保存される エクセルからは、「開く」から、「すべてのファイル」で読み込める
10
10 例題 EX10-3 一様な確率分布の乱数を複数個足した数は、正規分布(ガウス分 布)に従うことが知られている。いま、 0 ~ 9 の間に一様に分布す る整数の乱数を 10 個足し 5 で割った整数を X とする。 X を N 個発生さ せ、それぞれの数字が出た回数および確率を出力するプログラムを 作成せよ。 ( EX10-3.c) 結果の確率分布をエクセルでグラフにせよ。 #include int main(void) { int i,j,n_ev,rn; int ev[19]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0}; srand((unsigned int)time(NULL)); printf("Input number of events: "); scanf("%d",&n_ev); for(i=0; i<n_ev; i++){ rn=0; for(j=0; j<10; j++){ rn+=rand()%10; } rn/=5; ev[rn]++; } for(i=0; i<19; i++){ printf("%d %d\n",i,ev[i]); } return 0; }
11
配列を使ったベクトル、行列の計 算 複数の数の組を一括して扱う数学の概念に、 「ベクトル」と「行列」があります 「ベクトル」は添え字が1変数の配列を、 「行列」は添え字が 2 変数の配列を用いると C 言語で扱うことができます。
12
12 例題 EX10-4: 3X3 行列の配列による表現と画面出力 行列 を添え字が 2 変数の配列を用いて表現し、画面に出力せよ。 ( EX10-4.c) #include int main(void) { float m[3][3]={{1,2,3},{4,5,6},{7,8,9}}; int i,j; for(i=0; i<3; i++){ for(j=0; j<3; j++){ printf("%f ",m[i][j]); } printf("\n"); } return 0; } i 0 1 2 j 02 1 i 行 j 列の行列を配列 m[i][j] で表す 行 i のループの中に、列 j のループ( 2 重) 「 for 」ループを 2 重につかって、 内側のループ (j) で列を 外側のループ (i) で行を 繰り返して画面表示 1 列目 2 列目 3 列目 (j=0) (j=1) (j=2) 1 行目 1 2 3 (i=0) 2 行目 4 5 6 (i=1) 3 行目 7 8 9 (i=2)
13
13 例題 EX10-5 3次元ベクトルを2個入力し、2個のベクトルの、「和」、「差」、 「内積」を計算して表示せよ。 ( EX10-5.c) #include void inputvec(float a[3]); int main(void) { float a[3],b[3]; float sum[3],diff[3],inner_p=0; int i; inputvec(a); inputvec(b); for(i=0; i<3; i++){ /* 成分のためのループ */ sum[i]=a[i]+b[i]; /* 和の計算 */ diff[i]=a[i]-b[i]; /* 差の計算 */ inner_p+=a[i]*b[i]; /* 内積の計算 */ } printf(" 和 \t\t 差 \n"); for(i=0; i<3; i++){ printf("%f\t%f\n",sum[i],diff[i]); } printf(" 内積 : %f\n",inner_p); return 0; } void inputvec(float a[3]) { float w; int i; printf(" ベクトルの成分を入力してくださ い : "); for(i=0; i<3; i++){ scanf("%f",&w); a[i]=w; } タブ(一定の文字送り)
14
14 例題 EX10-6 3 X3 正方行列を2個入力し、2個の行列の和を計算して表示せよ。 また積の 1,1 成分を計算して表示せよ。 ( EX10-6.c) 2 次元配列なので、「 for 文」の2重ループで、 行 (i) のループの中に列 (j) のループを入れて成 分ごとに和を計算すればよい 積の 1,1 成分は行列 A の 1 行目と行列 B の一列目 について成分の積の和をとる
15
15 例題 EX10-6 3 X3 正方行列を2個入力し、2個の行列の和を計算して表示せよ。 また積の 1,1 成分を計算して表示せよ。 ( EX10-6.c) #include void inputmatrix(float a[3][3]); int main(void) { float a[3][3],b[3][3],sum[3][3]; float product[3][3]={{0,0,0},{0,0,0},{0,0,0}}; int i,j,k; inputmatrix(a); inputmatrix(b); for(i=0; i<3; i++){ for(j=0; j<3; j++){ sum[i][j]=a[i][j]+b[i][j]; } printf(" 和 \n"); for(i=0; i<3; i++){ for(j=0; j<3; j++){ printf("%f\t",sum[i][j]); } printf("\n"); } for(k=0; k<3; k++){ product[0][0]+=a[0][k]*b[k][0]; } printf(" 積の 1,1 成分 : %f\n",product[0][0]); return 0; } void inputmatrix(float a[3][3]) { int i,j; float w; for(i=0; i<3; i++){ printf(" 行列の %d 行めの成分を入力してくだ さい : ",i+1); for(j=0; j<3; j++){ scanf("%f",&w); a[i][j]=w; }
16
16 課題 EX10-7 3 X3 正方行列を2個入力し、2個の行列の積を計算するプログラ ムを完成させよ。 ( EX10-7.c) EX10-6.c では 1,1 成分について計算してい る i, j 成分を計算するにはどこを変更すれ ばよいか 「 for 文」で i と j についてループを回せば よい( EX10-6.c の inputmatrix() 関数を参 照) for(k=0; k<3; k++){ product[0][0]+=a[0][k]*b[k][0]; } ij
17
17 例題 EX10-8 ( 発展:任意の次元のベクトル ) 「 DIM 」次元ベクトルを2個入力し、2個のベクトルの、「和」、 「差」、内積を計算して表示せよ。「 DIM 」の値をいろいろ変えて コンパイルして結果を比較せよ。 ( EX10-8.c) #include #define DIM 3 void inputvec(float a[DIM]); int main(void) { float a[DIM],b[DIM]; float sum[DIM],diff[DIM],inner/_p=0; int i; inputvec(a); inputvec(b); for(i=0; i<DIM; i++){ /* 成分のためのループ */ sum[i]=a[i]+b[i]; /* 和の計算 */ diff[i]=a[i]-b[i]; /* 差の計算 */ inner_p+=a[i]*b[i]; /* 内積の計算 */ } printf(" 和 \t\t 差 \n"); for(i=0; i<DIM; i++){ printf("%f\t%f\n",sum[i],diff[i]); } printf(" 内積 : %f\n",inner_p); return 0; } void inputvec(float a[DIM]) { float w; int i; printf(" ベクトルの成分を入力してくださ い : "); for(i=0; i<DIM; i++){ scanf("%f",&w); a[i]=w; } 「 #define DIM 3 」とすると、以下の 「 DIM 」の部分が全て「 3 」に置き換わ る。 「 #define DIM 3 」を「 #define DIM 4 」と すれば4次元ベクトル用のプログラムに なる。
18
配列を使った連立方程式の解法 連立(代数)方程式は行列を用いて表すこと ができます⇒線型代数 係数部分を表す「係数行列」の逆行列が求ま れば、逆行列の掛け算によって、解は簡単に 求まります 行列、ベクトルを配列で表すことにより、2 変数 (x,y) 連立方程式を解くプログラムを作ろ う
19
2変数連立方程式と行列 2変数連立方程式の行列による表現 もし逆行列 A -1 が求まれば
20
2X2 行列の逆行列 2X2 行列の逆行列
21
21 例題 EX10-9 2X2 行列を入力し、逆行列を表示するプログラムを作成せよ。 ( EX10-9.c) #include #define DIM 2 void inputmat(float a[DIM][DIM]); int main(void) { float a[DIM][DIM],inv_a[DIM][DIM],determinant; int i,j; inputmat(a); determinant=a[0][0]*a[1][1]-a[0][1]*a[1][0]; if(determinant==0){ printf(" 逆行列は存在しない \n"); } else{ inv_a[0][0]=a[1][1]/determinant; inv_a[1][1]=a[0][0]/determinant; inv_a[0][1]=-a[0][1]/determinant; inv_a[1][0]=-a[1][0]/determinant; printf(" 逆行列 :\n"); for(i=0; i<DIM; i++){ for(j=0; j<DIM; j++){ printf("%f\t",inv_a[i][j]); } printf("\n"); } return 0; } void inputmat(float a[DIM][DIM]) { float w; int i,j; printf(" 行列の成分を入力してください :\n"); for(i=0; i<DIM; i++){ for(j=0; j<DIM; j++){ scanf("%f",&w); a[i][j]=w; }
22
22 課題 EX10-10 2X2 の係数行列と、 2 成分定数ベクトルを入力し、連立方程式を解 くプログラムを作成せよ。解が存在しない(不定、不能)場合には 「解なし」と出力すること。 ( EX10-9.c) 係数行列の逆行列を定数ベクトルに掛け て得たベクトルの成分が、解 x,y になる 逆行列が存在しないとき⇒「不定」、 「不能」の解なしに対応
23
23 特別課題 EX10-11 N 連の連立方程式を解くプログラムを作成せよ。解が存在しない (不定、不能)場合には「解なし」と出力すること。 ( EX10- 11.c) N 連の連立方程式を解くためには NXN 正 方行列(係数行列)の逆行列が求まれば よい NXN 正方行列の逆行列を求めるには、ガウ ス・ジョルダン法( Gauss-Jordan elimination) がある ⇒中学でならう消去法と同じもの ガウス・ジョルダン法の簡略化バージョン として、ガウス消去法( Gaussian elimination )がある WEB でアルゴリズムを調べてみよ(提出 にはおよばない)
24
実習結果のレポート 3つのソースファイル「 EX10-2.c 」、 「 EX10-7.c 」、「 EX10-10.c 」を添付ファイ ルにしてメールを送ってください。 宛先: muroo@cc.tuat.ac.jpmuroo@cc.tuat.ac.jp 件名:コンピューター基礎実験10 本文:感想および一言 24
Similar presentations
© 2024 slidesplayer.net Inc.
All rights reserved.