(7-1)[C] 繰り返し計算の考え方

[ トップ | 目次 | 前ページ | 次ページ ]


Cにおけるプログラミングの基本は,メモリーの状態の変更し目的の状態を作り出すことであった.このための基本構文がwhileやforなどの繰り返し構文である.そこで,この考え方に慣れるために,幾つかの関数を定義してみよう.

状態の設計

繰り返しコード設計の基本は,

  1. 求める値に至る(それを特別な場合として含む)計算の途中状態を設計し、
  2. 計算の途中結果の値を保持するための変数と
  3. 計算の進行状態を保持する変数を用意し,
  4. これら変数を更新するコードを書く

ことである。以下,簡単な例について、その計算状態と変数の設計方針を示す.

  • 1からnまでの積を求める(前のfactorialの例)
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = i * (i + 1) * ... * n
    • 最終状態:i = 0
  • 1からnまでの総和を求める
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = i + (i+1) + ... + n
    • 最終状態:i = 0
  • 1からnまでの整数の2乗の和を求める
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = i*1 + (i+1)*(i+1) + ... + n * n
    • 最終状態:i = 0
  • 1からnまでの整数の3乗の和を求める
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = i * i * i + (i+1) * (i+1) * (i+1) + ... + n*n*n
    • 最終状態:i = 0
  • xとyの積を足し算を使って計算する(積はyをx回足したもの)
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = xをi回足した結果
    • 最終状態:i = x
  • 与えられた数nをk乗する.
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = nの(k - i)乗
    • 最終状態:i = 0
  • 初項A(0)が1公差が2の等差数列のn番目の項A(n).(注)
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = i番目の項
    • 最終状態:i > n
  • 初項B(0)が1公比が2の等比数列のn番目の項B(n).
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = i番目の項
    • 最終状態:i > n
  • 初項C(0) = 1でC(n) = 2 + 3 * C(n-1)なる漸化式の一般公
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = i番目の項
    • 最終状態:i > n

(注1)高等学校などの数列の定義では,項には1から始まる番号がつけられるが,計算機でのプログラミングでは,番号は0から付けるほうが,自然で便利なことが多い.

ループによる実現

以上の方針が決まれば、対応する変数を宣言し、最終状態をループの終了条件とし、途中状態が保たれるようにループ内の文で変数を更新するコードを書けばよい。以下がその例である。

  • 1からnまでの積を求める(前のfactorialの例)
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = i * (i + 1) * ... * n
    • 最終状態:i = 0
int factorial (int n) {
 int s = 1, i = n;
   while (i > 0) {
     s = s * i;
     i = i - 1;
     }
   return s;
}
  • 1からnまでの総和を求める
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = i + (i+1) + ... + n
    • 最終状態:i = 0
int sum (int n) {
 int s = 0, i = n;
   while (i > 0) {
     s = s + i;
     i = i - 1;
     }
   return s;
}
  • 1からnまでの整数の2乗の和を求める
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = i*1 + (i+1)*(i+1) + ... + n * n
    • 最終状態:i = 0
int sigma2 (int n) {
 int s = 0, i = n;
   while (i > 0) {
     s = s + i*i;
     i = i - 1;
     }
   return s;
}
  • 1からnまでの整数の3乗の和を求める
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = i * i * i + (i+1) * (i+1) * (i+1) + ... + n*n*n
    • 最終状態:i = 0
int sigma3 (int n) {
 int s = 0, i = n;
   while (i > 0) {
     s = s + i*i*i;
     i = i - 1;
     }
   return s;
}
  • xとyの積を足し算を使って計算する(積はyをx回足したもの)
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = xをi回足した結果
    • 最終状態:i = x
int times (int x, int y) {
 int s = 0, i = x;
   while (i > 0) {
     s = s + y;
     i = i - 1;
     }
   return s;
}
  • 与えられた数nをk乗する.
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = nの(k - i)乗
    • 最終状態:i > n
int power (int n, int k) {
 int s = 1, i = k;
   while (i > 0) {
     s = s * n;
     i = i - 1;
     }
   return s;
}
  • 初項A(0)が1公差が2の等差数列のn番目の項A(n).(注)
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = i番目の項
    • 最終状態:i > n
int A (int n) {
 int s = 1, i = 1;
   while (i <= n) {
     s = s + 2;
     i = i + 1;
     }
   return s;
}
  • 初項B(0)が1公比が2の等比数列のn番目の項B(n).
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = i番目の項
    • 最終状態:i > n
int B (int n) {
 int s = 1, i = 1;
   while (i <= n) {
     s = s * 2;
     i = i + 1;
     }
   return s;
}
  • 初項C(0) = 1でC(n) = a + b * C(n-1)なる漸化式の一般公
    • 計算結果を持つ変数:s
    • 計算の状態を保持する変数:i
    • 途中の計算状態:s = i番目の項
    • 最終状態:i > n
int C (int n) {
 int s = 1, i = 1;
   while (i <= n) {
     s = 2 + 3 * s;
     i = i + 1;
     }
   return s;
}

テスト

これら関数を,これらを呼び出す以下のようなmain関数とともにファイルloops.cに定義してテストしてみよう.

main() {
  printf("factorial(10):%d\n", factorial(10));
  printf("sum(10):%d\n", sum(10));
  printf("sigma2(10):%d\n", sigma2(10));
  printf("sigma3(10):%d\n", sigma3(10));
  printf("times(2,3):%d\n", times(2,3));
  printf("power(2,3):%d\n", power(2,3));
  printf("A(10):%d\n", A(10));
  printf("B(10):%d\n", B(10));
  printf("C(10):%d\n", C(10));
}

コンパイル実行すると以下のような結果が得られるはずである.

C:\SMLSharpAndC\c>gcc loops.c
gcc loops.c

C:\SMLSharpAndC\c>a.exe
a.exe
factorial(10):3628800
sum(10):55
sigma2(10):385
sigma3(10):3025
times(2,3):6
power(2,3):8
A(10):21
B(10):1024
C(10):118097

[ トップ | 目次 | 前ページ | 次ページ ]