繰り返し処理(ループ)
1.このページでは,繰り返し処理を学びます.繰り返し処理はループとも呼ばれます.2.javascriptで使える繰り返し処理には,whileループ,do〜whileループ,forループがあります.
これら3種類のループのどれを使っても,ほぼ同じことができます.極端に言えば,3種類とも覚える必要はなく,1つできればよい.誰にでも得意・不得意はあり得ますが,この教材の管理人はforループだけを使っており,他の2つはほとんど使いません.
3.forループ
(1)処理が1つだけのとき
for(初期条件;継続条件;更新条件)
の形で書くことができます.処理1;
for(初期条件;継続条件;更新条件)
と書くこともできます.
{処理1;
}
タブキーを使ってインデント(字下げ)するのは,プログラミングする人が見やすく・間違いにくくするためのもので,コンピュータには何列目に書かれているかということによる区別はありません.しかし,間違いにくくすることは重要ですから,できるだけタブキーを使ったインデントをする方がよいでしょう.以下においても同様です.
|
(2)2つ以上の処理を行うときは
for(初期条件;継続条件;更新条件)
のように中かっこ{ }で囲まれた範囲(ブロック)が繰り返されるようにします.{処理1;
処理2; …; } もし
for(初期条件;継続条件;更新条件)
と書くと,処理1だけが繰り返され、処理2以下は繰り返されません.
処理1;
処理2; …; |
(3)forループを使う上での注意点
3.1)
for(初期条件;継続条件;更新条件)の後ろにセミコロン(;)を付けてはいけない
for(初期条件;継続条件;更新条件);と書くと
コンピュータは(1)のように
for(初期条件;継続条件;更新条件)
と解釈します.そうすると,処理内容が空文(;)になっているので,何も行われません.;
(2)の場合でも,
for(初期条件;継続条件;更新条件);
と書くと,コンピュータは{
}
for(初期条件;継続条件;更新条件)
と解釈して,空文(;)のみを実行するので,何も行われません.{ }で囲まれたブロックは,囲まれているというだけなので,単に1回だけ実行されます.
カーニハン&リッチ流の書き方(C言語の創始者の名前.その教科書でブロックの始まりを表す中かっこを行末に書くスタイルが用いられたので,その後よく使われるようになったが,そのスタイルで書かなければならない訳ではない.この教材の管理人は,K&Rスタイルにしていない.);
{ }
for(初期条件;継続条件;更新条件){
にすると,こうした間違いを防ぎやすい側面がありますが,{ }の初め・終りの対応関係が見た目の通りにならないので一長一短です.
…
} |
3.2)
forループでは, for(@初期条件;A継続条件;B更新条件)
において,@→「A→C→B」「→A→C→B」…{C処理;
} 以下「 」の繰り返しとなる
【例】 変数ss1に1以上10以下の整数の和を求めて,最後に1回表示したいとき
のように書いた場合,@初期条件が行われた後,A継続条件を満たしていないので,Cは一度も実行されずにループを出てしまいします.
3.3)
forループでは,A継続条件とB更新条件の組合せが,無限ループにならないように「よく考える必要があります」
国際団体が定めるjavascriptの仕様と各々のブラウザでの実装とでは細かな部分では違うことがありますが,Google Chrome 68.0...でテストしている限り,for( ; ; )のように,@初期条件, A継続条件, B更新条件が何も書かれていない場合は,それらの条件が「満たされている」と解釈され,無限ループになるようです.(やらかしてしまった!forever=永遠に→コンピュータの電源を切らないと止まらない)
【例】 変数ss1に1以上10以下の整数の和を求めて,最後に1回表示したいとき,次のようにB更新条件を書き間違ってしまうと,どこまで行ってもA継続条件を満たすことになり,ループを出られません.
|
【例1】
(解答例)forループを使って,1から100までの整数の和を求めて,画面に表示するプログラムを作ってください. この例では,更新条件でkk1が100になったら,まだ継続条件を満たしているので100は加えられます. 更新条件でkk1が101になったら,もう継続条件を満たしていないので101は加えられず,ループの外に出ます. (別解) この例では,更新条件でkk1が1になったら,まだ継続条件を満たしているので1は加えられます. 更新条件でkk1が0になったら,もう継続条件を満たしていないので0は加えられず,ループの外に出ます. |
【例2】
(解答例)forループを使って,1から100までの整数のうちで,3でも5でも割り切れない数の和を求めて,画面に表示するプログラムを作ってください. 整数aを整数bで割った余りは a % bで求められます.そこで,整数nが3で割り切れないという条件は n % 3 != 0 3でも5でも割り切れないという条件は (kk1 % 3 != 0) && (kk1 % 5 != 0) と書くことができます. 2632になります. |
3.4)
ループ(for, while,do〜while)に共通なこととして,「continue; 以後の処理を行わずにB更新条件に進む」「break; 以後の処理を行わずにループを出る」が使えます.ただし,二重ループになっているとき,break;で1つのループだけ出られます.
【例3】 (中国剰余定理からの出題)
(解答例)forループを使って,31で割れば17余り,41で割れば29余り,61で割れば11余る自然数の最小値を求めてください.(10000以下で調べてください). ※上のプログラムでは,目的とする整数kk1が見つかったら,目印の変数mark1を1にしてループを抜け出るようにしています. この目印がなくてもdocument.write(kk1);は働きますが,その場合は目的の変数が10000までに見つからなくて,kk1が10000になったためにループを出たとき,kk1の値が10000と表示されます.その値は,目的の整数ではないので,上の例のように,目的の整数が見つかった場合だけ表示するように工夫するとよいでしょう. 上のプログラムで,else continue;がなくても全く同じように働きます.(if(条件)が満たされない場合,明示的に else continue;でループに戻ると書かない場合でも,更新条件kk1++から継続条件の判断へとプログラムは流れていきます) ※表示される整数は,5318になります.(中国剰余定理というのがあって「a,b,cが互いに素な自然数のとき,a,b,cで割った余りが各々p,q,rとなる整数はa*b*cまでに唯1つ存在する」ことが知られています.次に大きいのは82849です)
【例4】
(解答例)forループを使って, となる整数nの最小値を求めて,画面に表示するプログラムを作ってください.ただし,無限ループにならないように(どこまでやっても10を超えないかもしれないから)n= 100000までで調べてください. |
【例5】
(解答例)正の整数が三平方の定理を満たすとき,整数の組はピタゴラス数と呼ばれます. 各々2けたの整数がピタゴラス数となるようなの最大値を求めてください. ※breakはif()のブロックを抜け出るかどうかには関係しません. 1つのbreakで抜け出られるループは一重だけです.上の例のように3重ループになっている場合に,三重とも抜け出るためには,(関数の中ならreturnという方法もありますが)目印となるカードを持たせて,カードの値が特定の値なら検問を通す(合言葉が合えば通すという感じ)方法が使えます. その他,ループにラベルを付けて,break, continueと同時にそのラベルに飛ぶ方法もあります.下記参照(ただし,BASICプログラムで利用可能なGOTO ラベルはjavascriptでは利用できません.また,ラベルの多用はスパゲッティ・プログラム[もつれてほどきにくいもの]になり勝ちなので,好まれません) ※数字としては,zが97のとき,65^2+72^2=97^2が成り立ちます. |
4.whileループ
while(A継続条件)
の形で,継続条件が満たされる限り繰り返されます.
{C
処理1; 処理2; … } forループにはあるBの更新条件がwhileループにはありませんので,Cの処理の過程で,「Aの更新条件を満たさないことが必ず起こる」とか「何らかの条件が整えばbreakする」など,ループを抜け出られるように書いてあることが重要です.この点について慎重に扱わないと無限ループに陥る可能性があります. 5.doループ
do
の形で,継続条件が満たされる限り繰り返されます.
{C
処理1; 処理2; … } while(A継続条件) doループもwhileループと同様に,Cの処理の過程で,「Aの更新条件を満たさないことが必ず起こる」とか「何らかの条件が整えばbreakする」など,ループを抜け出られるように書いてあることが重要です.この点について慎重に扱わないと無限ループに陥る可能性があります.
※手元の教科書には,doループは書かれていないが,実際には使える.若者好みの用語で言えば裏メニューとでも言うのかな.
|
6.どのループを使うか? 見た目のままに素朴に当てはめると (1) 1〜100までのようにカウンターとなる整数によって初めと終わりを指定しやすいときは,forループに当てはめやすい.
(2) 何個目で終わるかということは,データを読んでみなければ分からないような場合は,whileに当てはめやすい.
(3) whileと同様の事情があるが,少なくとも1回は処理を行いたいときは,doループに当てはめやすい.
と考えられますが,次のように対応させると,whileループ,doループでできることは,すべてforループでできます.
for(@初期条件;A継続条件;B更新条件)
{C処理; }
@初期条件;
while(A継続条件) {C処理; B更新条件; } ※@の初期条件をループの中に入れると毎回初期化されてしまう
@初期条件;
do {C処理; B更新条件; } while(A継続条件) ※@はループの前に置くこと,Bをループの中に書くことはwhileと同様
【例6.1】
forループが最適でしょう(//からその行の右端まではコメントで,コンピュータは読みません)を求めるには whileループで書けば doループで書けば |
おそらく終わりはあるが,何回目の繰り返しで終わるかを前もって指定しにくいとき
【例6.2】
forループで書けば
111回になります.整数論の未解決問題の1つにコラッツ予想(3n+1問題)というものがあって, nが2で割り切れれば2で割る nが2で割り切れなければ3を掛けて1加える という操作を繰り返すと,「2以上のどのような自然数nから出発しても必ず1に帰着する」というもので,内容は小学生でもわかるが証明は専門家でもできていないので定理と呼ばずに予想と呼ばれる. n=27の場合に何回の処理で1に帰着するか調べたい. whileループで書けば doループで書けば |
【例6.3】
forループで書けば
23になります.(2つ目の問題は1759)2つの正の整数a, b(a≧bとする)の最大公約数を求めたいとき,a, bの約数が分からないときでも計算できる方法として,ユークリッドの互除法があります. 次の操作を繰り返すと最大公約数が求まります.
aをbで割った余りをrとするとき,
次の各組の2数の最大公約数を求めてください.(713, 2921), (4061531, 6766873)
(1) rが0ならばbが最大公約数 (2) rが0でなければ,あらためてbをr(b>r)で割った余りを考えて,この操作を繰り返す 備考1:Google Chrome 68.0...では,for(;;)で見かけ上の無限ループになりますが,10年ほど前のInternet Explorerでは初期条件,継続条件,更新条件が空白のままでは繰り返しが行われなかったような記憶があります.(その場合は,for(1;1;1)のように各条件の値を明示的に1にするとよい) whileループで書けば 備考2:Google Chrome 68.0...では,while()のように継続条件が空白のままではエラーになります.while(1)のように明示的に1にすると見かけ上の無限ループになります. ※doループも同様ですが,上の6.3の答案例のように書くことは「絶対にループを抜け出られる」という自信がなければ,避けるべきです.Webページは他人も見るので,確実にループを出られるようにすべきです.(たとえば,カウンターを付けて10000回繰り返して,結果が出なければbreakするなど.一般に,PCの性能にもよりますが,1億回も繰り返すようなループは相当な負担です.練習用のプログラムなら,1000回とか10000回までで十分試してから使った方がよいでしょう) |