障害(バグ)の直接原因第三弾は、「丸め誤差」です。
丸め誤差による障害は、小数点以下の数値の扱い方に起因し、計算結果が想定と異なる事象となります。
ここでは、丸め誤差により障害がどのように発生するのか、その原因は何か、そして、その対策を学んでください。
丸め誤差による障害とは何か?
小数点以下の数値をどう扱うかが、「丸め」になり、丸めによって出された数値と本来の数値との差分が「誤差」となります。
丸め誤差とは何か?小数点以下の数値をどう扱うかを知る!で、丸め誤差について書いていますので、よければご覧下さい。
例えば、以下の場合を考えてみましょう。
10÷3=3.3333・・・・
これは、割り切れず、永遠と続く、いわゆる循環小数と呼ばれるものです。
本来の数値は、3.3333・・・です。ですが、これですとは言い切れません。
そこで、策として、小数点第三位を四捨五入し、その数値をもって、10÷3の値とします。
10÷3=3.33
本来の数値が「3.3333・・・・」、四捨五入の数値が「3.33」です。
この差分は、0.0033・・・・となります。
これが、丸め誤差というものです。
これを踏まえて、丸め誤差の障害ですが、実は、プログラム言語によって、勝手に丸めてしまう場合があります。これを理解していないと、想定外の計算結果になってしまうのです。
C言語を例に「10÷3」の場合の計算結果を説明していきます。
double型の変数d1に、10÷3を直接代入すると、結果は、3.000000になります。
Cコンパイラが勝手に、小数点以下を切り捨てています。
これを知らずに、3.3333・・・となると思い込んでいると、想定と異なってきます。
これが、丸め誤差による障害のひとつです。意図しない動作によって引き起こされた、計算結果差異になります。
しかし、これは、言語仕様を理解していれば容易に回避できるものです。
まず、なぜ、結果が3.000000になっているのかですが、演算が整数型で行われたからです。
10÷3=3と処理されたのです。
その結果をdouble型の変数に格納したから、結果は、小数点付きで、3.000000となったのです。
これを3.3333・・・としたい場合は、演算を実数型で行わせる必要があります。
つまり、10÷3ではなく、10.0÷3.0をd1に代入すれば、実数型として演算してくれます。
- 整数型として演算される:d1 = 10 /3; ---> 3.000000
- 実数型として演算される:d1 = 10.0 / 3.0; ---> 3.333333
この場合の障害の直接原因は、指定する数値を整数型にしていたことになります。
では、なぜ、整数型にしていたのでしょうか?それが根本原因になります。
丸め誤差の障害の根本原因とは?
丸め誤差による障害は、ここで取り上げた例以外にも多数存在しますが、意外と言語仕様の理解不足により引き起こされる障害が多発しています。
そうです。
この記事で取り上げている障害の根本原因は、「言語仕様の理解不足」なのです。
あるいは、言語仕様を理解していたが、うっかりミスで、整数型を渡していたというケースがあるかもしれませんが、恐らくそのケースは少ないのではないでしょうか?
演算というのは、言語系のコンパイラが司る場合と、データベースの演算機能のように、言語系以外の機能が司る場合があります。
そして、その精度により、誤差が生じることがあります。
ですので、小数点を扱う演算を行う場合は、必ず、仕様として明記することが必要です。そうでなければ、必ず、どこかで、計算結果異常が発生します。
特に、C言語側で行う演算と、データベース側で行う演算が混在するようなプログラムでは、精度の差により、更なる丸め誤差が発生しうるのです。
ですので、ここの計算は、言語側で、ここの計算は、データベース側でというように設計の段階で、明記しなければ、プログラマーの独断でやりやすい方でコーディングしてしまいがちです。
A機能では、言語側でのみ演算していて、B機能では、言語側とデータベース側、C機能では、データベース側でのみ演算しているというケースの場合、同じ計算をしていたとしても、結果が異なる可能性もあります。
その場合、どれが求められる数値なのか、信頼性に欠けてしまいます。
小数点を扱う計算式が存在する機能においては、その演算方針を設計としてきちんと明記すべきなのです。統一性を図るためにも重要です。
いずれにしても、小数点を扱う演算が存在するプログラムでは、単体テストにおいて、ひとつひとつテストを行い、想定する結果となっているかを検証していくことが重要です。
複雑な計算式であっても、ひとつひとつステップバイステップで演算結果を検証してください。ここは力を入れる箇所であることを肝に銘じてください。
関連記事)こちらも参考にしてみてください。
カテゴリ:問題管理