- 0-a
-
レポートには, 手書きでよいから説明をつけることを求めています.
プログラムのプリントアウトだけでは不十分です.
説明としては, たとえば以下のようなものがありましょう.
- 処理の説明 (「割り切れるならループから脱出する」など;
細かすぎることは書かなくて良い--「x を 0 にする」とか.)
- 変数の意味 (「それまでに見つかった素数の個数」など)
- プログラムで工夫した点
- 1-a
-
補助的な変数はあまり使わない方がいいでしょう.
ひとつの代入文で済むものはその方がいいと思います.
たとえば,
c = (a+1) / 100;
b = c + 1;
よりは
b = (a+1) / 100 + 1;
のほうがシンプルです.
- 2-a
-
整数と指定されている値を入れる変数は int 型にしたほうがよい.
- ☆2-b
-
素数を求める次のコードを見て下さい. これは二つの点で間違っています.
main()
{
int n, i, c;
scanf("%d", &n);
for(i=2; i<n; i++){
c = c * (n % i);
}
if(c != 0){
printf("%d is prime\n", n);
}
}
アイデアとしては, n を順次の整数で割ったあまりを掛け合わせていくことで,
ひとつでもゼロが現れたら結果がゼロになる, というもので,
数学的には正しい.
しかし,
- まず, 変数 c の初期値が指定されていない. 初期値の指定されていない変数の
値はどうなるかわからない(不定)ので, ひょっとしてそれが 0 だったら破綻する
- さらに重大なのは, 整数型には精度(つまり桁数)が有限しかないという
ことである. 2進数で32桁分しかないから, 2 を 32回掛けるだけで
表現可能範囲を越える(オーバーフローする).
その場合, 上の桁からはみ出した値は捨てられるのが普通なので, 結果はゼロになってしまう.
この例では, たとえば 97(素数) を入力してみると, 間違った結果になる.
- ☆2-c
-
main()
{
int n, i, r;
scanf("%d", &n);
for(i=2; i<n; i++){
r = n % i;
if(r == 0) break;
}
if(r != 0){
printf("%d is prime\n", n);
}
}
これはほとんどの場合うまく動きますが, n が 2 の場合に限って問題があります.
そのとき, for ループは一度も実行されません.
したがって, 変数 r は初期値(この場合は不定)のままで最後の if文に到達することに
なります.
偶然 r が 0 だった場合には間違った判断になります.
ループに入る前に, 「r = 1;」のように適当な初期値を与えておけばOKです.
あるいは, このプログラムでは, 「割り切れたので途中で脱出」と,
「割り切れないまま全回まわって終了」を区別できればいいので,
最後の if の条件として 「i == n」を使えばいいでしょう.
教訓
- 変数の初期値には気をつけよう (なにもしないと不定)
- ループは一度も回らない可能性があるので注意
- 3-a
-
整数と指定されている値を入れる変数は int 型にしたほうがよい.
- 3-b
-
課題3 レベル3 で, 重複する組合せを取り除くのに, a<=b となるものだけを
選ぶ必要があります.
この場合に, a, b, c をすべて 1 から 100 まで変化させて全組合せを試し,
そのなかで a<=b となる場合だけ結果を出力するという方法もあります.
しかし, これでは無駄が多いので, ループの繰り返し条件を工夫して,
for(a=1; a<100; a++){
for(b=a; b<100; b++){
のようにすると, 最初から a<=b となるものしか試さずに済みます.
- 3-c
-
課題3 レベル2 では, a, b, c のすべての組合せを試すわけですから,
三重のループになりますが, その初期値は論理的にはすべて 1 からとすべきでしょう.
(実際には, a*a+b*b==c*c をみたすのはもうすこし先の値からですが)
- 3-d
-
直角三角形の条件を調べるのに,
「c == sqrt(a*a+b*b)」とするよりは, 「c*c==a*a+b*b」のテストの方がシンプルだし,
実数型の精度の問題なども心配せずに済みます.
- 3-e
-
課題3 レベル3で, 三重ループのうちの c の初期値として, 1 から始めている
ケースがありますが, c*c==a*a+b*b をみたすわけですから, すくなくとも
b よりは大きいはずで, 初期値として b+1 くらいを与えてもいいと思います.
- 3-f
-
課題3 レベル3で, a<=b というのが重複を除外するための条件になる
わけですが, これを a<b としているケースがあります.
実際にはこの問題に限っていえば c*c==a*a+a*a には絶対にならないので,
これで問題はありませんが, 一般にすべての組合せを試そうとする場合には
注意しましょう.