解答は、「小数点の端数処理の食い違い」です。
今回の問題は、定義した商品データの合計金額を算出するプログラムでした。両者で値が食い違うのは、小数点の処理の方法の違いです。今回の面倒な箇所は、消費税を計算するため合計金額が、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セント未満の端数を自分の口座へ振り込むように不正なコーディングをしたのです。月に数十米ドルほど稼げると思ったのですが、実際には全顧客の端数が一斉に自分の口座へ流れ込んで数十万米ドルもの巨額になり、怖くなって自白したそうです。ちりも積もれば山となります。
下記に、自己採点シートを示します。
問題 | 項目 | 配点(点) |
---|---|---|
売上金額計算プログラム | 問題を一通り読んだ | 25 |
プログラムを一通り読んだ | 25 | |
小数点の端数処理が原因だと推察できた | 50 | |
リスト3 自己採点シート |
プログラムを顧客に見てもらうと、特定の入力条件で発生する不思議なバグが発生することがあります。今回は、筆者の経験から商品の合計金額を求めるプログラムを出題しました。たかが1円ですが、会計処理を扱うプログラムではクリティカルな問題でしょう。このような不思議なバグが発生しても、素早く原因を見つけ、顧客の納得できる説明ができるエンジニアを目指していただければと思います。
また、組み込みソフト業界でも、小数のデータを計算すると思います。今回の問題から、「数値の有効桁を含め正しい値を使っているか」「小数の切り捨て、切り上げ、四捨五入はどうなっているか」などをもう一度考えてみましょう。
東海大学 大学院 組込み技術研究科 非常勤講師(工学博士)
Copyright © ITmedia, Inc. All Rights Reserved.