PowerPoint

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