● ループで繰り返し計算

■ for ループ

▲ 1から10までの和を計算するプログラム(sample04.cc)

前章のプログラムがする計算は、わざわざプログラムを作って計算する よりも電卓でチョンチョンと計算するほうがずっと簡単でした。
では、1から10までの整数の総和を求める計算はどうでしょう。 公式を使わずにこれをそのまま計算するのは電卓ではちょっと面倒です。 プログラムでも sum=1+2+3+4+...+10と書くのも楽ではないですし、 これが1000までの総和となれば、無理な作業です。

そこで必要になるのがループと呼ばれる機構です。ループとは 輪のことで、この輪の中の計算が何度も実行されます。 以下のプログラムを見てください。

// sample04.cc
#include <stdio.h>

main(void)
{
  int n;  // 変数の宣言
  int sum = 0; // 変数の宣言と初期化
    
    // for ループ
  for( n=1 ; n<=10 ; n++ ){
      sum += n;  // 足し上げる
  }
    
  printf("The sum is %d\n", sum );
}

int sum=0; は変数の宣言と代入を一緒にしてしまう方法です。 このような宣言と同時の代入を初期化と呼びます。

forループの所の()になにやらいろいろ書かれていますが、 これが for文のループの仕方を決める重要な設定なのです。 その書式は以下の通りです。

for( 初期化文 ; ループ条件文 ; ループ変更文){
ループ実行文(複数可);
}

上のプログラムでは、まずプログラムの実行がこの for文に来ると、 まず初期化文が実行されます。つまり n=1 です。
次にループ条件文が評価されます。つまり n<=10 です。もしこれが 真ならループ実行文が実行されます。偽ならこの for 文を終了して次の printf文に移ります。
ループ実行文がすべて実行されるとループ変更文が実行されます。 ここでは n++ です。この n++ というのは整数 nの値をひとつだけ増やす 命令です。
ループ変更文が実行された後、再びループ条件文が評価されます。
こうしてループ条件文が偽になるまで{ }で囲まれた文が何度も実行 されます。sum+=n; というのはsumの値をnだけ増やすという命令です。 こうして1から10までの和が計算されます。

もう一度説明しておきましょうか。
実行がfor文に入る前には sumの値は 0になっています。for文に入ると まず n=1がなされます。次に n<=10 がチェックされます。nは 1なのです からこれは真です。よって{ }の中の sum+=n が実行されます。
sumの値が 0で nの値が 1なのでこの命令によって sumの値は1増えて1に なります。
次に n++ で nが 2になります。またn<=10がチェックされます。これも 真なのでsum+=nが実行されます。今度はsumは2増えることになります。 これで 1+2 がなされたわけです。これを繰り返してnが11になったとき ループが終了します。こうして 1から10までの総和が求まったわけです。


■ while ループ と do while ループ

ループ文にはforループのほかにもwhileループとdo whileループが あります。forループは返し回数が自明な場合によく使われるのに対して、 whileループとdo whileループは繰り返し回数が自明でない場合に よく使われます。

whileループの書式は以下の通りです。

while( ループ条件文 ){
ループ実行文(複数可);
}
ループ条件が満たされる場合にループ内の命令を実行するわけです。 なので始めからループ条件が満たされなければループ内の命令を 一度も実行しないことになります。

do whileループの書式は以下の通りです。

do{
ループ実行文(複数可);
}while( ループ条件文 );
ループ内の命令を一度実行してからループ条件を検査するのです。 つまりループ条件が満たされる場合にループ内の命令をもう一度 実行するわけです。なので無条件で最低一度はループ内の命令が 実行されます。


▲ 平方根を繰り返し計算で求めるプログラム(sample05.cc)

do whileループの使用例として平方根の値を sqrt()関数を使わずに 四則演算の繰り返しだけで計算する方法を紹介しましょう。

// sample05.cc
#include <stdio.h>

// 与えた x に対する y = sqrt(x) を計算する。
main(void)
{
  double x, y;
  double a, da;
    
  printf("Input a positive number =");
  scanf("%lf", &x );  // 正の実数をキーから読み込む。
    
  a = x;     // aの値をまずこうする
    
    // do while ループ
  do{
    da = 0.5*(a - x/a);      // a の減少分 da を計算する
    a -= da;                 // a を da だけ減らす
  }while( da > 0.000001 ); // 減少分がこの程度大きい間ループを続ける

  y = a; // これが答えの値

  printf("The root of %lf is %lf.\n", x, y );
}

プログラム冒頭の scanf はキーボードから値を読み込んで指定の 変数にその値を代入する命令です。実数 x にキーからの値を受け付けるには このようにします。scanf()関数については後で詳しく説明します。

このループでは変数 a の値を da だけ修正する作業を何度も 繰り返します。修正分 daが大きい間ループを繰り返すので、つまり 修正分 da が十分小さくなればループが終ります。修正分の大きさで ループを繰り返すか判定するのでこの場合 do whileループが 効果的です。でも同様の作業はforループでもwhileループでも なんとか作ることはできます。

このような計算で平方根が計算される理由を簡単に説明します。 数学的な話なので興味の無い人は読み飛ばして下さい。
指定したxに対する y = sqrt(x) を計算することは、 y*y - x == 0 となる yを見つけることと同じです。(負符合は気にしない) yの値として試しにある適当な値 a を置いてみて、 a*a - x を 計算すると、その値は普通0ではないでしょう。ここで、aの値を微少量 da だけ減らすと a*a - x の値は 2*a*da だけ減ることに注目しましょう。 a*a - x の値が0まで減るにはあと、a*a - xだけ減らせば良いわけです から、大雑把に見積もって、a の値を

da = (a*a - x)/(2*a) = 0.5*(a-x/a)
だけ減らせばかなり良い線までいくでしょう。 この変更作業を何度も繰り返せばやがて解となるのです。
方程式の解を求めるこのような方法をNewton法と呼びます。 減少分daの値は必ずしも常に正とは限らないので、 sample05.ccでのループ条件文 da > 0.000001 は万能ではありません。


■ if文

ループではないのですけれど非常に大事な文があります。それは 条件分岐文if文です。ある条件が満たされているときのみに命令を行う という例外処理がよくあります。if文は簡単です。書式を示します。  

if(条件文){
条件文が真のときに実行する命令群;
}else{
条件文が偽のときに実行する命令群;
}
elseより後の部分はもし偽の命令群が無いのなら省くことができます。  やはり、ひとつ例をお見せしたほうがよろしいでしょう。
if( a < 0 ){
  a = -a;
}
これで絶対値が計算されるわけです。


■ break文とcontinue文

ループの中で突然ループから出たくなる場合があります。そういうとき には break命令を使います。またループで次のステップに強制的に飛びた いときはcontinue命令を使います。例を見てください。

 
while(a<b){
    ループ実行文
    if(ループ脱出条件文)break;
}
for(a=1;a<10;a++){
    if(ループネクスト条件文)continue;
    ループ実行文
}
実際に作ってみてその効果を確認しておいてください。


  • 次へ
  • 目次
    Copyright(C) by Naoki Watanabe. Oct 21st, 1995.
    This page was modified on Aug 3rd, 1998.
    渡辺尚貴 naoki@cms.phys.s.u-tokyo.ac.jp