バグ検出ドリル(19)たかが1円されど1円……1円足りないバグの恐怖:山浦恒央の“くみこみ”な話(119)(3/3 ページ)
バグは至るところに、しかも堂々と潜んでおり、自信満々なプログラマーほど、目の前のバグに気付かないものです。「バグ検出ドリル」の第19回の問題は、商品と個数から合計金額を求めるプログラムのバグです。なぜか1円だけ合わない、このバグの原因を突き止めよう!
4.今回の解答
解答は、「小数点の端数処理の食い違い」です。
今回の問題は、定義した商品データの合計金額を算出するプログラムでした。両者で値が食い違うのは、小数点の処理の方法の違いです。今回の面倒な箇所は、消費税を計算するため合計金額が、1円未満の小数になる場合があることです。表3-1の合計金額を手計算すると、((444+531+776+2295)×1.08)となり、4396.68円となります。バグの原因は、小数点以下の端数処理の食い違いです。詳しく見ていきましょう。
A君のプログラム(リスト2)をご覧ください。ここで、合計金額を格納する変数total1、total2はint型です。int型の場合は小数点以下を切り捨てるため、結果は4396円になります。
B君の結果を確認しましょう(リスト3-1)。B君の合計金額は、4397円となっています。つまり、B君は小数点以下を四捨五入しています。
では、なぜ表1-2のデータで、二人の計算結果が一致したのでしょうか。このデータの合計金額は、((2368+4779+9797+6120)×1.08)は、24909.12円です。A君は、小数点以下を切り捨てるため、24909円となります。B君は、小数以下を四捨五入しますが、こちらも24909円です。結果として、両者の結果が偶然一致する不思議なバグとなりました※4)。
本問題とは違う事象ですが、小数点の端数処理のバグは、筆者が小規模なショッピングサイトのソフトウェアを開発時に体験したものです。合計金額の計算を顧客がチェックしたところ、「画面によって、端数の処理が違うのですが」と指摘があり、入力データをいろいろ変えて、バグを見つけました。普段使う紙幣やコインには、小数はありませんが、実際には端数処理をしています※5)。
※4)ちなみに、B君の合計金額の端数処理は、Excelのセルの書式設定に依存しています。Excelは、非常に便利なツールですが、目に見えない箇所にいろいろなパラメータがあるので、惑わされないように注意しましょう。
※5)今から50年以上前の有名な話ですが、米国のある銀行がコンピュータを初めて導入しました。その時のプログラマーが、利息計算で生じた1セント未満の端数を自分の口座へ振り込むように不正なコーディングをしたのです。月に数十米ドルほど稼げると思ったのですが、実際には全顧客の端数が一斉に自分の口座へ流れ込んで数十万米ドルもの巨額になり、怖くなって自白したそうです。ちりも積もれば山となります。
5.自己採点シート
下記に、自己採点シートを示します。
問題 | 項目 | 配点(点) |
---|---|---|
売上金額計算プログラム | 問題を一通り読んだ | 25 |
プログラムを一通り読んだ | 25 | |
小数点の端数処理が原因だと推察できた | 50 | |
リスト3 自己採点シート |
6.終わりに
プログラムを顧客に見てもらうと、特定の入力条件で発生する不思議なバグが発生することがあります。今回は、筆者の経験から商品の合計金額を求めるプログラムを出題しました。たかが1円ですが、会計処理を扱うプログラムではクリティカルな問題でしょう。このような不思議なバグが発生しても、素早く原因を見つけ、顧客の納得できる説明ができるエンジニアを目指していただければと思います。
また、組み込みソフト業界でも、小数のデータを計算すると思います。今回の問題から、「数値の有効桁を含め正しい値を使っているか」「小数の切り捨て、切り上げ、四捨五入はどうなっているか」などをもう一度考えてみましょう。
東海大学 大学院 組込み技術研究科 非常勤講師(工学博士)
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- ≫連載「山浦恒央の“くみこみ”な話」バックナンバー
- バグ検出ドリル(18)IoT時代だからこそ重要、単純でも検出が難しい通信系バグ
バグは至るところに、しかも堂々と潜んでおり、自信満々なプログラマーほど、目の前のバグに気付かないものです。「バグ検出ドリル」の第18回の問題は、相互に通信する機器のソフトウェアのバグです。IoT時代を迎えて利用場面が増えている、通信系のバグを見つけ出しましょう! - バグ検出ドリル(17)「よくある単純なバグ」だからこそ見つけにくい
バグは至るところに、しかも堂々と潜んでおり、自信満々なプログラマーほど、目の前のバグに気付かないものです。「バグ検出ドリル」の第17回の問題は、前回と同じ音楽プレーヤーのプログラムから出題します。「よくある単純なバグ」が潜んでいますが、見つけ出せますか? - バグ検出ドリル(16)音楽プレーヤーに潜むバグを見つけ出せ
バグは至るところに、しかも堂々と潜んでおり、自信満々なプログラマーほど、目の前のバグに気付かないものです。「バグ検出ドリル」の第16回の問題は「簡単なバグなのに、なかなか見つからない」バグです。何で見つからないんだ! - バグ検出ドリル(15)なぜ「山田三郎」が「まだまだ天田三郎」に化けるのか
バグは至るところに、しかも堂々と潜んでおり、自信満々なプログラマーほど、目の前のバグに気付かないものです。「バグ検出ドリル」の第15回の問題は、「思った通りに動いてくれないプログラム」のバグです。少しはプログラマーに忖度してくれよ! - バグ検出ドリル(14)タイポグリセミア現象もびっくり、恐るべきは思い込み
バグは至るところに、しかも堂々と潜んでおり、自信満々なプログラマーほど、目の前のバグに気付かないものです。「バグ検出ドリル」の第14回の問題は、前回に続いて「煮詰まったバグ」です。煮詰まっているがゆえに、バグの原因が分からなくなる事態に対処してください!