このページをはてなブックマークに追加このページを含むはてなブックマーク このページをlivedoor クリップに追加このページを含むlivedoor クリップ

目次

演算により生じる誤差

 コンピュータは計算処理を有限の桁数で行うため、実数を行うほとんどの計算において誤差を生ずる。その結果、計算によって求めた数値には「有効な桁」と「有効でない桁」が含まれていることになる。数値の表現形式や演算の種類によって、誤差の種類が異なる。

有効数字と有効桁

 有効な桁を有効数字、その桁数を有効桁数と呼ぶ。

[例]

  • 「1234」の有効桁数は4
  • 「12.30」の有効桁数は4
  • 「0.012」の有効桁数は2
  • 「1200」の有効桁数は4または2
    • 1.200×103とすれば、有効桁数は4桁
    • 1.2×103とすれば、有効桁数は2桁

計算結果と有効桁数

 計算処理において、計算対象となるそれぞれの数値の有効桁数が異なる場合には、次の規則にしたがい有効桁数が決まる。

和・差の場合

 加減算は絶対値の大きい数字の有効桁数に揃えて計算する。

[例]

  • 1.23456(有効数字6桁)+87(有効数字2桁)=88(有効数字2桁)
  • 123,456(有効数字6桁)-1.2(有効数字2桁)=123,455(有効数字6桁)

積・商の場合

 乗除算は有効数字の小さい方にそろえて計算する。

[例]

  • 1.23456(有効数字6桁)×3.4(有効数字2桁)=4.1(有効数字2桁)
  • 3.45678(有効数字6桁)÷1.2(有効数字2桁)=2.8(有効数字2桁)

絶対誤差と相対誤差

 誤差の大きさを見積もる方法には、絶対誤差相対誤差の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%誤差である。

桁切り誤差(打切り誤差)

 技術計算などにおいては、処理を続ければより精度の高い値が得られるとしても、値がある程度収束してきたところで処理を打ち切って結果を出す。このときに生じる誤差が桁切り誤差(打切り誤差)である。

例:無限和、無限小数、円周率の計算など

情報落ち

 浮動小数点演算で絶対値が著しく異なる数値(絶対値の非常に大きい数と非常に小さい数同士)の加減算行うとき、小さな数値が計算に反映されなくなる。この現象を情報落ちという。

 演算対象の数の指数部が異なるとき、指数部の小さいほうを大きいほうに合わせる調整が行われ、与えられた桁内では表現できない場合があるからである。

 情報落ちを防止するには複数の数値の加減算では、絶対値の小さい順に数値を並べ替えて計算を行うようにする必要がある。

[例]

 小数点の位置が揃うように絶対値の小さい数値を調整してから計算が行われる.この際、有効桁数を越えてしまう可能性があり、結果的に絶対値の小さい数値が無視される。

  • 絶対値が極端に離れた2つの値で加算や減算を行うと、小さい方の値が無視される。
    • 例えると、8桁表示の一般的な電卓では、「1000000+0.00001」の計算結果を「1000000」と表示することに似ている。

[例]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
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>サンプル</title>
</head>
 
<body>
<h1>サンプル</h1>
<script>
// 小数点演算
console.log(0.3 * 3);    // 0.8999999999999999
 
// 正しい小数点演算
// 値を整数にしてから演算を行い、その結果を少数に戻すことによって解決する.
console.log(((0.3 * 10) * 3) / 10);    // 0.9
</script>
<p></p>
</body>
</html>

 誤差が小さくなるデータ型を用いて防止する。

[例]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コードを使う方法

 BCDコードを使えば2進数で10進数を表現することができる。

参考文献

  • 『The BUG』
  • 『プログラムはなぜ動くのか』
  • 『ソフトウェア開発技術者 午前対策(基礎編) テキスト』
  • 『ソフトウェア開発技術者 合格エッセンシャルハンドブック』
  • 『超図解mini 基本情報技術者試験 平成19年度版』
  • 『情報処理技術者試験ポケットスタディ 応用情報技術者』
  • 『2001秋 徹底解説 基本情報技術者本試験問題』


*1 信頼できる桁