C プログラミング入門 基幹7 (水5) 05: 反復 (1) Linux にログインし、以下の講義ページ を開いておくこと http://www-it.sci.waseda.ac.jp/ teachers/w483692/CPR1/ 2016-05-11 1 制御構文 条件分岐(第4回) ループ(今回・次回) if - else for (switch – case) while (goto) do - while 2 今日の内容 今回 次回 便利な演算子 累積誤差 while 文 多重ループ do-while 文 break, continue for 文 カンマ演算子 3 ループでよくつかわれる演算子(復習) 複合代入演算子 a += 8 などなど (a = a + 8 と同じ) インクリメント・デクリメント a++ a-- ++a --a (a = a + 1 と同じ) (a = a - 1 と同じ) 4 例題1:一般角の正規化 一般角 a [deg] を半開区間 [0, 360) に正規 化する 360 以上の場合は、繰り返し 360 を引く 負の角度の場合は、繰り返し 360 を足す 1035 [deg] =360×2+315 315 [deg] 5 while 文 構文 while (条件式) 文; while (条件式) {ブロック} 条件を満たす (真である) 間、 文またはブロックを繰り返し 実行する 反復、ループなどと呼ぶ 式の評価 偽 真 ブロックの実行 先判定ループ 条件によっては一度も実行され ない 6 例題1:一般角の正規化 一般角 a [deg] を半開区間 [0, 360) に正規 化する 360 以上の場合は、繰り返し 360 を引く 負の角度の場合は、繰り返し 360 を足す /* 正の角の正規化 */ while(a >= 360) { a -= 360; } /* 負の角の正規化 */ while(a < 0) { a += 360; } それぞれ一行で書くこともできる。 while(a >= 360) a -= 360; 7 例題1:一般角の正規化 実行例 ... double a = 1035; /* 正の角の正規化 */ while(a >= 360) { a -= 360; } ... a 1035 675 315 8 例題2:ニュートン法 平方根 2 に収束する数列を計算する 2 は 𝑓 𝑥 = 𝑥 2 − 2 = 0 の根の1つ 以下の漸化式で定義される無限数列 𝑥0 , 𝑥1 , 𝑥2 , … , 𝑥𝑛 , … は適当な 𝑥0 ≠ 0 から始めて ± 2 のいずれかに収束する 𝑥𝑛+1 𝑓 𝑥𝑛 = 𝑥𝑛 − ′ 𝑓 𝑥𝑛 𝑥𝑛2 − 2 = 𝑥𝑛 − 2𝑥𝑛 一般にこの計算で f(x) = 0 の根を求める方法をニュー トン法という 9 例題2:ニュートン法 𝑥𝑛+1 = 𝑥𝑛 − 2 −2 𝑥𝑛 2𝑥𝑛 ループを使わずに解くためには、何度も同じ 計算式を書くしかない double x0 = 1.0, x1, x2, x3, x4; x1 = x2 = x3 = x4 = ... x0 x1 x2 x3 – – – – (x0*x0 (x1*x1 (x2*x2 (x3*x3 – – – – 2) 2) 2) 2) / / / / (2*x0); (2*x1); (2*x2); (2*x3); 数列の分だけ変数 を書かないといけ ない 同じ式が何度も繰 り返される 10 例題2:ニュートン法 𝑥𝑛+1 = 𝑥𝑛 − 2 −2 𝑥𝑛 2𝑥𝑛 最終的な結果のみを残せばよいので、1つの変 数を次々に上書きする double x = 1.0; x = x = x = x = ... x x x x – – – – (x*x (x*x (x*x (x*x – – – – この値は、上書き されて失われる 2) 2) 2) 2) / / / / (2*x); (2*x); (2*x); (2*x); 同じ式が何度も繰 り返されるのは変 わらず 11 例題2:ニュートン法 𝑥𝑛+1 = 𝑥𝑛 − 2 −2 𝑥𝑛 2𝑥𝑛 while ループで繰り返し処理をまとめる 終了条件が何か必要 double x = 1.0; while( 条件式? ) { x = x – (x*x – 2) / (2*x); } ... この値は、上書きされて 失われる 一つの式だけになった 12 例題2:ニュートン法 𝑥𝑛+1 = 𝑥𝑛 − 2 −2 𝑥𝑛 2𝑥𝑛 𝑓 𝑥 = 𝑥2 − 2 繰り返し条件として、 𝑓 𝑥 場合 double x = 1.0, e = 1.0e-5; while(fabs(x*x-2) > e) { x = x – (x*x – 2) / (2*x); } ... > 𝑒 を採用する 閾値 10−5 繰り返し条件 f(x) がゼロ に近づくまで 計算する fabs() は絶対値を求 める関数 (math.h) 13 do-while 文 構文 do 文; while(条件式); do {ブロック} while(条件式); 文またはブロックを実行し た後、条件を判定して、真 の間繰り返す 後判定ループ 必ず一度は実行される ブロックの実行 真 式の評価 偽 14 例題3:ニュートン法 繰り返し条件として、 𝑥𝑛+1 − 𝑥𝑛 > 𝑒 を採用 する場合 前回の値と比較するので、まずは1回計算が必要 double x = 1.0, xx, e = 1.0e-5; do 一つ前の値を取っておく { 変数 前回の値を 取っておく xx = x; x = x – (x*x – 2) / (2*x); fabs() は絶対値を求 } める関数 (math.h) while(fabs(xx-x) > e); 前回の値との 差を調べる ... 15 for 文 構文 for(初期化式; またはブロック ; 条件式 ) 文; 更新式 初期化式の評価 1. 最初に初期化式を評価 普通は代入式がかかれる 2. 文またはブロックを実行 3. 更新式を評価 4. 条件式が真なら 2. に戻る 偽 条件式の 評価 真 ブロックの実行 更新式の評価 16 ループ変数を使った for 文 ループ変数(ループカウンタ)により反復回 数を制御 i, j, k, n, m などがよくつかわれるが, 何でも可 int i; // ループ変数 初期化式 条件式 i++ でもよい 更新式 for(i = 0; i < 10; ++i) { printf("%d ", i); } 0 1 2 3 4 5 6 7 8 9 ▮ 1. 初期化 3. 実行 i = 0 i < 10 printf() 4. 更新 ++i 2. 条件判定 丁度10回 繰り返している ループ終了後 の値 i 10 17 for 文の更新式の例 更新式の異なるループの結果 for(i=0; i < 10; i=i*i+1) { printf("%d ", i); } 0 1 2 5 ▮ i 26 for(i=0; i < 10; i=i+3) { printf("%d ", i); } 0 3 6 9 ▮ i 12 for(i=0; i < 10; --i) { printf("%d ", i); } 0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 … 変数 i の表現範囲を超えると正の値になって止まる可能性はある 18 for と while の関係 for は while に特別な処理を加えたもの 等価な書き換えが可能 int i; int i; 初期化式 条件式 更新式 for(i = 0; i < 10; ++i) { printf("%d ", i); } i = 0; while(i < 10) { printf("%d ", i); ++i; } 19 どれを使えばいいの? 固定回数繰り返す場合 for while でも可能 (等価書き換え) ある条件の下で不定回数繰り返す場合 先に条件を判定するなら while 計算結果から条件を判定するなら do-while 20
© Copyright 2024 ExpyDoc