SML# - Tutorial/007-1 Diff

  • Added parts are displayed like this.
  • Deleted parts are displayed like this.

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

!状態の設計
繰り返しコード設計の基本は,
# 求める値に至る(それを特別な場合として含む)計算の途中状態を設計し、
# 計算の途中結果の値を保持するための変数と
# 計算の進行状態を保持する変数を用意し,
# これら変数を更新するコードを書く
ことである。以下,簡単な例について、その計算状態と変数の設計方針を示す.

* 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
----
[ [[トップ |Tutorial]]| [[目次|Tutorial/000]] | [[前ページ|Tutorial/007]] | [[ 次ページ |Tutorial/008]] ]