どうしたらいいかの前になぜそうなったかを考えましょう。
それがわからなければ,どうすればいいのかはわかりません。
なぜそうなったかを調べる手段の一つは,丹念にコードを追うことです。
このサイズなら机上でも十分だと思いますが,
実際にデバッガ上で動かして一行ずつ進めながら変数の値を確認していく,というのは基本的なデバッグ方法です。
とりあえず机上デバッグ。
3を入力した場合に,fact関数は,
- 18行目 : i = 0, n = 3, c = 3, n > i : true
- 20行目 : i = 0, c = 3, c - i = 3, n = 9
- 18行目 : i = 1, n = 9, c = 3, n > i : true
- 20行目 : i = 1, c = 3, c - i = 2, n = 18
- 18行目 : i = 2, n = 18, c = 3, n > i : true
- 20行目 : i = 2, c = 3, c - i = 1, n = 18
- 18行目 : i = 3, n = 18, c = 3, n > i : true
- 20行目 : i = 3, c = 3, c - i = 0, n = 0
- 18行目 : i = 4, n = 0, c = 3, n > i : false
というループの過程を経ます。
これを見れば,問題点がわかると思います。
まず,20行目での計算がおかしいことがすぐにわかります。
最初にc - iが3であるのがそもそもおかしいわけですが,単純にiが0の時にnに2をかければよいとばかりに
とするとi=c-1の時にnが0になり正しい結果がでません。
これらは,i=0ではなくi=1から始めることで解決します。
次に,ループの継続条件のうちのnがどんどん変化していることがわかります。
階乗の計算では計算回数は変化しないはずなので,nが変化するのもおかしいことになります。
これは,継続条件をnではなくcを元にすることで,解決します。
2点をまとめて,
コード:
for (i = 1; i < c; ++i)
{
n *= c - i;
}
これを追うと,
- 1行目 : i = 1, n = 3, c = 3, i < c : true
- 3行目 : i = 1, c = 3, c - i = 2, n = 6
- 1行目 : i = 2, n = 6, c = 3, i < c : true
- 3行目 : i = 2, c = 3, c - i = 1, n = 6
- 1行目 : i = 3, n = 6, c = 3, i < c : false
となり,少なくともnが3の場合において正しい結果が得られていることがわかります。