(続き)
「sum = sum + i」も同様。 ++, -- については K&R2 §2.8 に述べられている。
上のプログラムで入力する数を 10, 100, 1000, 10000, ... のようにだんだん大きくしてゆくと、 どこかで int 型の限界を越えて答えがおかしくなる。 その場合でもエラーメッセージなどは一切出ない。 (やってみよう。)
この例では for を使うほうが自然であろうが、 while を使って書いてみたのが次である。
#include <stdio.h> /* ユーザが数を入力すると,1 からその数までの和を出力 */
main() {
int i, n, sum;
printf("いくつまで足しますか?\n");
scanf("%d", &n);
sum = 0;
i = 1;
while (i <= n) {
sum = sum + i;
i++;
}
printf("1 から %d まで足すと %d です.\n", n, sum);
}
#include <stdio.h>
main() {
int i;
for (i = 0; i < 10; i++) {
printf("i の値は %d です.\n", i);
}
}
これを改造してみよう。
次のプログラムは、 誤差の関係で、想像されるようには動かない。 (想像してから動かしてみよ。)
#include <stdio.h>
main() {
double x;
for (x = 0; x < 1; x = x + 0.1) {
printf("x の値は %f です.\n", x);
}
}
アラレ(霰)数とは
次のプログラムは、ユーザが入力した数から始めて 1 になるまで、 この数列を出力する。 ここでは while を使うほうが自然であろう。
#include <stdio.h> /* アラレ数 */
main() {
int n;
printf("自然数を入れてください.\n");
scanf("%d", &n);
while (n != 1) {
if (n % 2 == 0) { /* n が偶数のとき */
n = n / 2;
} else { /* n が奇数のとき */
n = 3 * n + 1;
}
printf("%d ", n);
}
printf("\n");
}
※ 入力した数が大きすぎたり、負の数を入力したりすると、 無限ループに陥ることがある。 そのばあいは Ctrl+C (Ctrl を押しながら C)を押す。 プログラムは Ctrl+C で中止できることが多いから、 必ず慣れておくこと。
※ ここで中カッコが入れ子になった場合のインデントのしかたを説明する。 上のプログラムの while の部分で確かめてみるとよい。
#include <stdio.h> /* 自然対数の底 e の計算 */
main() {
int n;
double sum, factorial;
sum = 1;
factorial = 1;
for (n = 1; n < 24; n++) {
factorial = factorial * n;
sum = sum + 1 / factorial;
printf("第 %d 項までの和は %.53f です.\n", n, sum);
}
}
自然対数の底 e を e = 1/0! + 1/1! + 1/2! + 1/3! + ...
として計算している。
C言語には階乗を表わす演算子はないので自力で計算しなければならない。
ここでは n! を計算した結果を捨てないで次の (n+1)! の計算に使っている。
「factorial = factorial * n」のところでは double 型と int 型とを掛けている。 この場合、結果は double 型になる。 C言語はこのあたりが煩雑である。 K&R2 §2.7, A6 に出ているが、 とりあえずは int と double しか使わないので 「int と double との演算結果は double になる」 とだけ覚えておけばよい。
※ 岩波「数学辞典第3版」1434 ページによれば e = 2.7182818284590452353... であり、 上のプログラムの計算結果は途中で違っている。 コンピュータの計算は近似計算なので、 むやみに桁数を多く表示させても意味がないときもある。
「かつ」や「または」は次のように書く。 これらは for や while の条件部にも使える。 K&R2 では §2.6 を見よ。
if ((x > 0) && (x < 8)) { /* 「かつ」 */
........
}
if ((x < 0) || (x > 2)) { /* 「または」 */
........
}
なお、x > 0 などを囲んでいる小カッコは実は不要である。
これについての詳細は K&R2 §2.12 を参照。
※ 「かつ」も「または」も同じ文字を二つ打つことに注意。 まちがって「&」「|」をひとつだけ書いた場合、 それらにも意味があるのでコンパイラはエラーメッセージを出さない (かもしれない)。
次のプログラムは九九の表を出力する for を二重に使っていること以外は、 いままでに習ったことでわかると思う。
#include <stdio.h>
main() {
int i, j;
for (i = 1; i <= 9; i++) {
for (j = 1; j <= 9; j++) {
printf(" %d", i*j);
}
printf("\n");
}
}
全部やらなくても構いません。 むずかしさはまちまちです。
1 から 1 まで足すと 1 です.
1 から 2 まで足すと 3 です.
....
1 から 10 まで足すと 55 です.
と出力されるようにせよ。
| 1 2 ... 9 ---+--------...---- 1 | 2 | : : 9 |のように被乗数・乗数を左と上に出力するようにしてみよ。
0 は偶数です. 1 が奇数です. 2 は偶数です. ... 9 は奇数です. 10 は偶数です.のように出力されるプログラムを書け。
for (i = 0; i < 10000; i++) {
for (j = 0; j < 10000; j++) {
sum = sum + (i + j); /* 意味のない適当な計算 */
}
}
はどのくらい時間がかかるか? 回数を変えていろいろ調べてみよ。
必要なら三重以上のループも使え。