teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

追記

2018/04/29 02:09

投稿

KSwordOfHaste
KSwordOfHaste

スコア18404

answer CHANGED
@@ -2,4 +2,18 @@
2
2
 
3
3
  つまり正しくない答えが出るケースがあるのは確かです。コンパイル結果にwarningがあっても結果が正しければWAにはならないと思います。
4
4
 
5
- 質問者さんの修行の邪魔になるといけないので具体的なエラーケースについては言及を控えますが・・・最初にやってみたケースで見つかりました。
5
+ 質問者さんの修行の邪魔になるといけないので具体的なエラーケースについては言及を控えますが・・・最初にやってみたケースで見つかりました。
6
+
7
+ ---
8
+ 追記:質問者さんが降参して正解回答をごらんになったとのことで本件のWAの原因についてコメントします。
9
+ 自分が見つけた問題は「調べる数が10000のとき、それが何ケタかを求める論理の間違い」です。調べる数が1~9999までの値の場合は桁数kが正しく求まりますが10000のとき、
10
+ `if( (float)num[j] < powf(10, (float)i) ){`
11
+ この行の条件が成立しません。この行はforループの中にありますが、iは0~4まで変化しますので不等号の右辺は1, 10, ..., 10000と変化しますが`<`が成立しませんよね?そのため条件が成立した際の処理
12
+ `k = i - 1`が実行されずループ完了時点でkは-1になります。これが原因で以降の論理が破綻します。
13
+
14
+ **デバッグの際のコツ**ですが、論理を確認しても間違いが見つからない場合、**まずNGとなる条件を見つける**ことで突破できることがあります。また多くのNGケースは「境界ケース」です。本件についていえば自分が最初にテストしたのはたまたま境界ケースである「10000 1 36」でした。範囲内の全ての値についてテストがパスしなければならないケースですね。実際その入力でテストしたところ49995000という結果になったため一目で「これはどこかにバグがある」と分かりました。というか本来の値50005000とちょうど10000の差があるので「おそらく10000のケースがまずいのだろう」と想像できました。しかしここで「10000がまずい」と決めつけず「本当に10000がテストをパスしなかったのか」を確認した方がよいだろうと思いました。デバッグの際には「事実を一段階ずつ確実につかむ」のが鉄則です。確認せぬまま推測で先に進めることもありますが万一その推測が間違っていると時間を大分無駄にしてしまいます。10000がNGかどうかはループの中でall_sumに加算している部分でデバッグプリントしてみれば一発でわかります。実際確認してみると確かに10000が加算されてないことが判明しました。
15
+ ここまでくると原因究明はほぼできたも同然です。10000の場合のみ各論理がどのように動作するか集中してよーく見てみればいいのです。もしそれでもわからなかったらデバッグプリントを入れて「ループが何回まわるか」「各if文の判定結果は期待通りか」「変数の値がポイントポイントで期待どおりの値か」をつぶさにデバッグプリントで確認すれば、コードを目で見てあれこれ考えなくても「事実」が簡単につかめます。
16
+
17
+ コードを目で眺めただけで経験豊富なプログラマーであれば「バグに気づく」ことはできます。しかしそれは初心者には難しいです。初心者の方は「実際に動かして変数の値やプログラムが走行した道筋がどうなのかの事実を調べる」のがお勧めです。
18
+
19
+ (なお、本件に直接関係しませんが、本問題に浮動小数点演算は余計であると感じるプログラマーは多いと思います。整数演算で充分と思います。)