基礎プログラミング 第9回(2007年5月14日) 数値データと配列,多次元配列 配列のコピー 配列の要素の検索と並び替え (ソート) 2次元配列(行列) 1 配列の「コピー」は=でできる?? 1: 2: 3: 4: 5: 6: 7: 確認プログラム(1:~7:は行番号) int[] orig, copy; orig = new int[3]{2,3,5}; copy = new int[3]; copy = orig; for(int i=0;i<3;i++) copy[i] *= 2; foreach(int n in orig) Console.WriteLine(n); foreach(int n in copy) Console.WriteLine(n); 2 1: for(int 2: 3: 4: int[] = orig copy orig, =i=0;i<3;i++) new new orig; copy; int[3]{2,3,5}; int[3];copy[i]*=2; 5: int[] 型の 変数orig int[] 型の 変数copy 0 0 1 2 4 2 6 3 10 5 1 2 3 本当に配列を「コピー」するには 1: 2: 3: 4: 5: 6: 7: (1:~7:は行番号) int[] orig, copy; orig = new int[3]{2,3,5}; copy = new int[3]; for(int i=0;i<3;i++) copy[i] = orig[i]; for(int i=0;i<3;i++) copy[i] *= 2; foreach(int n in orig) Console.WriteLine(n); foreach(int n in copy) Console.WriteLine(n); 4 1: for(int 2: 3: int[] = orig copy orig, =i=0;i<3;i++) new new copy; int[3]{2,3,5}; int[3]; 5: for(int copy[i]*=2; 4: i=0;i<3;i++) copy[i]=orig[i]; int[] 型の 変数orig int[] 型の 変数copy 0 1 2 2 3 5 0 1 2 4 6 10 5 Array.Copy() メソッドを使う方法 (1:~7:は行番号) 1: int[] orig, copy; 2: orig = new int[3]{2,3,5}; 3: copy = new int[3]; 4: Array.Copy(orig, copy, orig.Length); 5: for(int i=0;i<3;i++) copy[i] *= 2; 6: foreach(int n in orig) Console.WriteLine(n); 7: foreach(int n in copy) Console.WriteLine(n); 6 コピーの際の注意点 3: copy = new int[3]; を忘れると,配列としての 容器が準備できていないのでコピーできない コピー先配列の長さが短いと全部コピーできない オリジナル(orig)の配列サイズが不明なときや変更 される可能性がある場合は, copy = new int[3]; のように「数値」で直接書かずに copy = new int[orig.Length]; のように作成したほうが変更の手間が少なくて便利 7 文字列の配列のときはどうなる? 1: 2: 3: 4: 5: 6: 7: 8: (1:~8:は行番号) String[] orig, copy; orig = new String[3]{”守”,”破”,”離”}; copy = new String [3]; for(int i=0;i<3;i++) copy[i] = orig[i]; String temp; temp = copy[1]; copy[1] = copy[2]; copy[2] = temp; 8 1: copy[2] 3: String[] copy =copy[1]; orig,String[3]; copy; 4: 5: 6: 7: 8: for(int String temp copy[1] =temp; i=0;i<3;i++) =new copy[2]; temp; copy[i] = orig[i]; 2: orig=new String[3]{“守”, “破”, “離”}; String[] 型の変数 orig String 型の変数 temp String[] 型の変数 copy 0 1 2 守 破 0 1 離 2 9 配列要素の初期化をfor文で行う インデックスと同じ値を入れる int[] a = new int[20]; for(int i=0;i<a.Length;i++) a[i] = i; インデックスの3倍の数値を入れる int[] a = new int[20]; for(int i=0;i<a.Length;i++) a[i] = i*3; インデックスのn乗の数値を入れる int[] a = new int[20]; for(int i=0;i<a.Length;i++) a[i] = Math.Pow(a[i],n); //a[i]の累乗 ×a[i]^n 10 フィボナッチ数列の計算 ★実例1★[13fib] f[n] = f[n-1] + f[n-2] の関係式が成り立つ数列 (ダヴィンチ・コードにもでてくる有名な数列) double[] fib = new double[40]; fib[0] = 1; fib[1] = 1; for(int i=2 ; i < fib.Length ; i++) fib[i] = fib[i-1] + fib[i-2]; (fibの中身) 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...11 練習問題9-1 [13fib] 黄金比 1 5 1.6180339887... 2 フィボナッチ数列の隣り合う数の比は,徐々に 「黄金比」に近づくことが知られています. ★実例1★で求めたf[38]とf[39]を使って f[39]/f[38]を計算し,上の黄金比と比べてみましょう. ★実例1★ では f[0] = 1, f[1] = 1 でスタートし ましたが,他の数でやったらどうなるでしょうか? 数列をどこまで計算すれば上の小数点以下10桁 まで合った数値になりますか? 参考:ちなみに√は,Math.Sqrt(数値)で計算でき ます(Square rootの略) プログラムでは使わなくてもかけますが 12 平均値の計算 double sum=0, average; double[] d = new double[10] {7,6,5,4,6,8,3,5,9,6}; //数字は無意味 for(int i=0 ; i<d.Length ; i++){ sum += d[i]; } average = sum / d.Length; Console.WriteLine(“平均は {0}”,average); 13 配列のなかから一番大きい数を見つけ る(ただし,Array.Sort() は使わずに) ★実例2★[14sortarray] int max = 0; int[] ary = new int[]{7,6,5,4,6,7,8,9,6}; for(int i=0; i < ary.Length ; i++){ if (max < ary[i]) max = ary[i]; } Console.WriteLine(“最大の値は {0}”,max); 14 練習問題9-2 (少し難易度の高い問題) 配列の並び替え(ソート) [14sortarray] intの配列 ary に入っている正の数値を,別 のintの配列sorted に大きい順に並び替えて ください (★実例2★を参考にする) ただし,Array.Sort()は使わず,aryで一番大 きい数値を探し, 1つずつ順番にコピーして いってください コピー済みの数値は0以下の数(任意)に置 き換えてください(配列 ary からデータを消し てよい) 最後にsortedの中身を表示し確認すること 15 配列aryのコピー済み数値は消す ary ary -1 7 6 5 4 6 -1 7 -1 8 -1 9 6 sorted 16 2次元配列 2次元配列変数の定義 int[,] matrix; 配列の作成 matrix = new int[2,2]; 初期化 matrix[0,0] = 0; matrix[0,1] = 1; matrix[1,0] = 10; matrix[1,1] = 11; 2つめの添字 ↓ 列 ↓ 1つ めの 添字 0 1 行→ 0 0 1 行→ 1 10 11 0 1 10 11 17 2次元配列(九九の計算) int[,] kuku = new int[10,10]; //都合上10にしておく for(int i = 1; i <= 9 ; i++){ for(int j = 1 ; j <= 9 ; j++){ 0 1 2 3 4.. kuku[ i , j ] = i * j; 0 } 1 1 2 3 4 } 2 2 4 6 8 3 4 5 : ★なぜ都合上10x10の配列に したのだろうか? 9でも格納できるはずなのに... 3 4 5 6 9 12 8 12 16 10 15 20 18 行列計算★実例3(前半)★ double[,] a = new double[3, 2]{{1, 2}, {2, 1}, {0, 1}}; // 3行2列の行列 double[,] b = new double[2, 3]{{1, 2, 0}, {0, 1, 2}}; // 2行3列の行列 double[,] c = new double[3, 3]; // 3行3列の行列 // これから,行列を表す配列a,bの積を計算し,配列 cに入れていきたい(次ページ) 1 2 c00 1 2 0 c10 2 1 0 1 0 1 2 c 20 c01 c02 1 4 4 c11 c12 2 5 2 c21 c22 0 1 2 19 行列計算★実例3(後半)★ for(int i=0; i<a.GetLength(0); i++) { // a.GetLength(0) は a の行数(=3)を表す for(int j=0; j<b.GetLength(1); j++) { // b.GetLength(1) は b の列数(=3)を表す c[i, j] = 0; for(int k=0; k<a.GetLength(1); k++) { // a.GetLength(1) は a の列数(=2)を表す c[i, j] += a[i, k] * b[k, j]; } 1 2 c00 c01 c02 1 4 4 1 2 0 } c10 c11 c12 2 5 2 2 1 0 1 0 1 2 c } 20 20 c21 c22 0 1 2 練習問題9-3 行列計算[15mulmatrix] ★実例3★のプログラムを入力し, (1)行列a,bの作成と値の代入 (2)行列cの作成 (3)aとbの積をcに計算 の3つの処理がどこでどのように行われている かを理解しなさい. 行列cの中身を画面に表示し,計算があって いることを確認しなさい. 自分が確認しやすいように表示を工夫すること 数値を替えて,試してみよう 21 練習問題は,完成したらなるべく早く, 必ずコミットすること (コミットメッセージは自由) できれば授業中に!! 変数,条件分岐,ループ,配列 の4つに慣れてもらうためにしばらく足踏みし, 次回も配列,ループに関連した話題とする 22 今後の予定 ( 9) 5/14 数値データと配列 / 多次元配列 (10) 5/16 文字列データと配列 / 可変長配列 (11) 5/21 関数 (12) 5/23 関数(メソッド) / オブジェクト指向 (13) 5/28 オブジェクト指向 / クラス定義 継承の概念は説明しない (14) 5/30 GUIをもつプログラムの構成法 GUIは試験範囲外 (15) 6/4 最終試験 @K12 23
© Copyright 2024 ExpyDoc