文書番号: 402554 - 最終更新日: 2004年5月20日 - リビジョン: 1.2 [XL] 浮動小数点の計算誤差と IEEE フォーマットこの記事は、以前は次の ID で公開されていました: JP402554 目次概要
本文書では、Excel 5.0 を始めとする多くのアプリケーションで問題となる数値の 「誤差」について、若干技術的に解説をしています。 コンピュータの数値表現私達はほとんどの場合 10 進数で計算を行います。しかし、コンピュータにとっては 2 進数の方が便利です。コンピュータは電気的に動作しており、その電気のオ ンかオフの状態を「 1 」と「 0 」として捉えるのが最も簡単だからです。この最小単 位を「ビット」と呼びます。1 ビットでは 2 種類、4 ビットでは 16 種類の表現が 可能です。このビットを増やすことで、扱える表現数は増えることになります。 コンピュータのメモリは無限ではありません。円周率や循環小数などを完全に表す ことは不可能です。そこである一定の桁でまるめてしまうことが必要になりま す。メモリは (ハードディスクなどに比べると) 比較的高価なデバイスですの で、できるだけ少ないメモリでできるだけ大きな数字や小さな数字を表現する という相矛盾する要求を満たさなければなりません。また、1 つの数値を表す のに少ないメモリであれば計算速度も向上します。これらのことを踏まえて、 いくつもの数値データの格納形式が発明されました。当初コンピュータは科学 技術計算に用いられることを目的として作られましたので、精度よりも、計算 速度や扱える数値範囲の大きさの方が優先されていました。その中で生まれたのが 今回ここで紹介する IEEE の浮動小数点フォーマットです。 Intel 系 CPU を使ったパーソナル コンピュータIntel 系の CPU (80386、80486、Pentium など) および数値演算プロセッサは IEEE(後述) で定められた数値のフォーマットに則ってデザインされており、このフォー マットでの演算コマンドをハードウェア レベルでサポートしています。このためこ の CPU を使ったオペレーティング システムおよびその上で動作するアプリケー ションは、自動的にこのフォーマットに従ったものになります。これ以外のフォ ーマットを使用したときには、ソフトウェアで演算の総てを行わなければなりま せんので、速度的には大きなペナルティとなります。Intel 系 CPU でサポート されている数値フォーマットおよびその派生は以下の通りです。
整数 (Integer)
長整数 (Long Integer)
単精度実数 (Single)
倍精度実数 (Double)
長倍精度実数 (Long Double)
数点演算プロセッサ (ユニット) が無いときにはソフトウェアでエミュレートしま す。例えば、i80386 CPU は標準でこのユニットを持っていません。別途専用の i80387 コプロセッサが用意されており、これと組み合わせることで実数の演算を ハードウェアで行うことができます。これに対し、i80486DX や Pentium プロセッ サなどは、その内部に浮動小数点演算ユニットを内蔵しています。 IEEE の浮動小数点フォーマットIEEE 形式は、米国電気電子技術者協会 (Institute of Electrical and Electronics Engineers) により、おもにパーソナル コンピュータで使用される浮動小数点の形式を統一するために定められました。808x6 を含む 16/32 ビット CPU に対応する コンパイラなどがこの規格に統一されており、80x87 などの数値演算コ・プロセッ サとも相性のよい標準的なデータ形式です。
単精度 倍精度
指数部ビット数 8 11
符号ビット数 1 1
仮数部ビット数 23 52
有効桁数 7 15
浮動小数点形式への格納による誤差浮動小数点数は小数点の位置を一定とせず、有効数字を表現する仮数部と小数点の位置 を示す指数部を用いて表します。指数部は数値の大きさの範囲を定める部分で、2 の べき乗を 2 進数で表現します。負の値の指数は、相対的なバイアス値を加算すること により表現します。仮数部は数値の精度を定める部分で、この値に指数部の計算を施して元の値を表現します。この仮数部の大きさが 4 バイト長の浮動小数点数を 「単精度」、8 バイト長の浮動小数点数を「倍精度」といいます。まず、この段階 で小数点以下の数値は精度が落ちます。多くの小数点以下の数値は上記の方法では 完全な精度での 2 進数化ができません。 また浮動小数点演算において、許容範囲を越える負の指数が生じたときは桁落ち (アンダーフロー) が発生します。また、仮数部の有効桁数を越えた数値を表現 するとき、超越分をなくさないため値を左右にシフトし、それに伴って指数部の 増減を行います。この操作を正規化といいますが、正規化が行われると誤差が生じ 精度が落ちます。このため実数の場合には循環小数となって完全に表現しきれない ことがあります。この誤差は計算上問題となりますので、保証できる精度の範囲を もって、「有効桁数」という言葉で表します。 Excel 5.0 の場合には 15 桁が有効桁数です。つまり 15 桁以上のところには 誤差が含まれている可能性があるということです。しかし、この誤差を含んだ 数値を演算した結果、14 桁以内に誤差が現れることもあります。 Excel 5.0 上での数値データの扱いExcel 5.0 では、数値は 2 種類のフォーマットで扱われます。1 つは整数で、もう1 つは実数です。整数は -32,768 から +32,767 までの小数点を含まない数値で、 それ以外の数値はすべて IEEE 形式の倍精度実数扱いです。いったんセルに入力 された整数の範囲を越える数値は IEEE 形式の浮動小数点フォーマットに変換さ れてメモリに格納されます。 そして瞬時に、指定された書式で変換して画面に表示します。したがいまして、入力 された数値がそのままセルに表示されているとは言っても、有効桁数の範囲外の部分 もしくは表示形式によって表現される範囲外の部分に誤差を含んでいる可能性がある ことになります。 ここで表示される桁より下の桁をどう処理するかが問題となります。この処理を 「まるめ」と呼んでいますが、これにも IEEE で幾つかのルールが決められてい ます。パーソナル コンピュータの世界では、「最近偶数値 の 2 の数値まるめ」 という方法を取っています。この処理は Excel 5.0 というよりもハードウェアも しくは Windows が行っています。さらに詳しいことがお知りになりたいときには、 IEEE の規格書もしくは Intel 社の 80x87 の仕様書を参照ください。 Excel 5.0 上での計算方法既定値では、Excel 5.0 は表示されている値ではなく、セルに保管されている値で行っています。すなわち実数では演算誤差を含んでいる可能性があります。また、 整数同士の演算で、結果も整数の範囲で収まるものは誤差は伴いません。しかし、 それ以外の場合には一端実数にキャスト (型変換) された後、演算が行われます。こ のときにも演算誤差を含むことがあります。ほとんどの場合、これらの誤差は有効 桁数外で発生しますので問題になることは、そう多くはありません。ただし、有効 桁数の範囲内では同じ数値であっても、範囲外の値が異なっているときには IF 関 数などによる比較で問題となるケースも発生します。これらのときには ROUND 系の 関数でまるめを行ったあとに比較をすることで回避できます。 表示されている値 (桁数) で計算させたいときには、[ツール] - [オプション] コ マンドの [計算方法] パネルで、[表示桁数で計算] チェックボックスをオンに することで行えます。この設定は、[オプション] コマンドで設定することから も判るとおり、Excel 5.0 全体に影響を与えます。また表示形式によって表示桁 数を指定しているときには、正確さも失われる可能性がありますので、設定にあ たっては十分な注意が必要です。 参考: VBA での通貨型Microsoft(R) Visual Basic(R)Programming System Applications Edition 内部には通貨型というデータ型を持っています。これは浮動小数点形式のフォーマットで は無く、固定小数点形式の独自のフォーマットです。浮動小数点と異なり、小数点 の位置を固定することで扱える数値の範囲は狭くなりますが、誤差を含ませないと いう利点があります。このため、金額を扱う計算のために使われるデータ型として 定義されています。 この型の有効桁範囲は整数部 15 桁+小数点以下 4 桁です。これは Microsoft(R) Visual Basic(R) for Windows(R) / MS-DOS(R)、Microsoft(R) BASIC Version 7.0 でサポートされているものと同じです。 サンプル
Sub Sample()
'計算に使用する変数を通貨型で定義します
Dim Kingaku As Currency, Zeiritsu As Currency
'計算に使用する値を変数に代入します
Kingaku = 1995
Zeiritsu = 1.03
'計算結果を整数にして値を求めます
Kingaku = Int(Kingaku * Zeiritsu)
MsgBox Kingaku
End Sub
計算結果を整数化する必要がある場合には、目的の処理に応じて Int、Fix などの VBA 関数を使用するか、Round、RoundDown、RoundUp などのワークシート関数を使用 して調整するようにしてください (サンプルでは、Int 関数を用いて計算結果を整数 化しています)。 各関数の機能および詳細は、オンライン ヘルプを参照してください。
"Microsoft Knowledge Baseに含まれている情報は、いかなる保証もない現状ベースで提供されるものです。Microsoft Corporation及びその関連会社は、市場性および特定の目的への適合性を含めて、明示的にも黙示的にも、一切の保証をいたしません。さらに、Microsoft Corporation及びその関連会社は、本文書に含まれている情報の使用及び使用結果につき、正確性、真実性等、いかなる表明・保証も行ないません。Microsoft Corporation、その関連会社及びこれらの権限ある代理人による口頭または書面による一切の情報提供またはアドバイスは、保証を意味するものではなく、かつ上記免責条項の範囲を狭めるものではありません。Microsoft Corporation、その関連会社 及びこれらの者の供給者は、直接的、間接的、偶発的、結果的損害、逸失利益、懲罰的損害、または特別損害を含む全ての損害に対して、状況のいかんを問わず一切責任を負いません。(Microsoft Corporation、その関連会社 またはこれらの者の供給者がかかる損害の発生可能性を了知している場合を含みます。) 結果的損害または偶発的損害に対する責任の免除または制限を認めていない地域においては、上記制限が適用されない場合があります。なお、本文書においては、文書の体裁上の都合により製品名の表記において商標登録表示、その他の商標表示を省略している場合がありますので、予めご了解ください。" |

先頭へ戻る
