コンピュータは計算処理を有限の桁数で行うため、実数を行うほとんどの計算において誤差を生ずる。その結果、計算によって求めた数値には「有効な桁」と「有効でない桁」が含まれていることになる。数値の表現形式や演算の種類によって、誤差の種類が異なる。
有効な桁を有効数字、その桁数を有効桁数と呼ぶ。
[例]
計算処理において、計算対象となるそれぞれの数値の有効桁数が異なる場合には、次の規則にしたがい有効桁数が決まる。
加減算は絶対値の大きい数字の有効桁数に揃えて計算する。
[例]
乗除算は有効数字の小さい方にそろえて計算する。
[例]
誤差の大きさを見積もる方法には、絶対誤差と相対誤差の2種類がある。
浮動小数点演算において、絶対値のほぼ等しい2つの数値を減算したときに、有効桁*1数が少なくなる現象を桁落ちという。有効桁が減ることで、真の値との間に生ずる誤差である。
正規化により有効桁数が減少するが、見かけの精度だけは高い。
例えると、「3-2=1.000…」としても、意味なく連続したゼロは演算精度とまったく関係ないことに似ている。
絶対値のほぼ等しい2つの数値を減算した場合、仮数部の先頭から多くの桁が0になる。この結果、仮数部の正規化が行われるために発生するものである。
桁落ちを防止するには絶対値のほぼ等しい同符号の減算をできるだけなくすように計算式を工夫する必要がある。
[例]
[例]1.1011×21-1.1010×21=0.0001×21=1.0000×2-3
桁落ちの本質的な問題は、「有効桁数の減少により、結果的にほとんど誤差のみになってしまう」ことである。上記の例では、123.456と123.454のいずれも末尾の桁に誤差を含んでいる場合、その数値自体に占める割合は10-5(=0.001%)程度であるが、減算の結果(0.002)は100%誤差である。
技術計算などにおいては、処理を続ければより精度の高い値が得られるとしても、値がある程度収束してきたところで処理を打ち切って結果を出す。このときに生じる誤差が桁切り誤差(打切り誤差)である。
例:無限和、無限小数、円周率の計算など
浮動小数点演算で絶対値が著しく異なる数値(絶対値の非常に大きい数と非常に小さい数同士)の加減算行うとき、小さな数値が計算に反映されなくなる。この現象を情報落ちという。
演算対象の数の指数部が異なるとき、指数部の小さいほうを大きいほうに合わせる調整が行われ、与えられた桁内では表現できない場合があるからである。
情報落ちを防止するには複数の数値の加減算では、絶対値の小さい順に数値を並べ替えて計算を行うようにする必要がある。
[例]
小数点の位置が揃うように絶対値の小さい数値を調整してから計算が行われる.この際、有効桁数を越えてしまう可能性があり、結果的に絶対値の小さい数値が無視される。
[例]1.1011×21+1.000×2-12=1.1011×21+0.0000000000001×21=1.1011×21
計算結果を指定された桁数に収めるために、最下位からあふれた数を切り捨て・切り上げ・四捨五入などの端数処理をする。端数処理を行うことを丸めるという。このとき、真値との間で生じる誤差のことを丸め誤差という。
[例]1/3=0.3333…のように、コンピュータに記憶可能な桁数を超える計算では丸められるので、丸め誤差が生じる。 ◇
[例]tを計算するときに、t=x2-xとするより、t=x(x-1)とした方が計算の精度がよくなる。 ◇
特に、小数点以下の数値の一部は、2進数では正確に置き換えることができず、無限小数となることがある。コンピュータは桁数が決まっているので、無限小数を扱うことができないので、無限小数を丸め処理を施す。
[例]JavaScriptでの例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
◇
誤差が小さくなるデータ型を用いて防止する。
[例]34.56を四捨五入または切り上げると34.6、切り捨てると34.5になる。 ◇
演算結果の値がコンピュータの表現範囲の上限を越えてしまうことをオーバーフロー(桁あふれ)という。シフト演算によっても発生する。
演算結果の値がコンピュータの表現の下限を超えてしまうことをアンダーフローという。シフト演算によっても発生する。
例えば、Javaの場合、int型からfloat型へ暗黙の型変換が行われる。その場合、floatの仮数部(23ビット)よりint(32ビット)の方が大きいので、intの値によっては型変換により精度落ちが発生してしまう。詳細は型変換の注意点を参照せよ。
プログラムの目的によっては計算結果のわずかな誤差がまったく問題にならない場合もある。一般に科学技術計算といわれている分野では、コンピュータの計算結果として近似値が得られれば十分である。つまりちょっとした誤差は無視できるわけだ。
小数点数の計算で誤差が発生してしまうコンピュータであっても、整数の計算では扱える値の範囲内であればきちんと誤差なしで計算される。例えば金銭計算は計算誤差が許されないので、誤差には注意しなければならない。
このアプローチを実現化する方法はいくつかある。
計算するときだけ一時的に整数を使い、計算結果を小数点数で表示するという方法がある。
[例]0.1を100回足し算する計算を、0.1を10倍して1にしてから100回足して、その後に10で割る。
[例]Visual BasicのCurrency型は通貨型といい、こうした処理を自動的に行ってくれる。
BCDコードを使えば2進数で10進数を表現することができる。