【実施例】
【0016】
最も簡単に本発明を実現するには、数値と誤差を対で扱うデータ構造を定義すればよい。
図2はこの一例を示すプログラムのソースリストであり、誤差を持つデータをC++のクラス“Real”のオブジェクトとして扱うことで、変数の値と誤差分散を対で扱っている。なお、このソースコードはマイクロソフト社製のVisual C++言語により記述されている。同言語に関しては非特許文献2などに詳しく述べられている。
【0017】
図2の(1a)(1b)(1c)はクラスRealのオブジェクトを生成するためのコンストラクタである。(1a)は数値を表す文字列を与えることにより、値と誤差分散の対を発生させ、これを生成されたオブジェクトの初期値とする。コンストラクタ(1a)の本体部分(15)は
図3に示されている。このプログラムは、文字列を変数の値に変換すると同時に、文字列に含まれる仮数部最下位桁の重みを求め、これを自乗することで誤差分散を得ている。(1b)は値と誤差の標準偏差の双方を与えてクラスRealのオブジェクトを形成する際に使用されるコンストラクタである。(1c)は初期値を与えず領域のみを確保する際に使用されるコンストラクタであり、各要素は0に初期化される。
図2の(2)はクラスRealのオブジェクトを文字列に変換するためのメンバ関数であり、数値を有効桁のみを含む指数形式の文字列(1.2e3などの形式)に変換した結果を返す。この関数の本体(16)も
図3に示されている。
【0018】
図2の(3a)から(3d)までの部分はクラスRealに対する四則演算を定義した部分で、値(val)をそれぞれ加減乗除するとともに、演算結果の誤差分散(err)を求めている。(4a)と(4b)はクラスRealの関数を定義する部分であり、ここでは平方根と絶対値化関数の定義を行っている。ここでは一例として二つの関数定義のみを示した。アプリケーションプログラムを作成する際には他にもさまざまな関数が使用されるが、これらに対してはReal型を扱う関数を別途定義して使用する。(5)はクラスRealのメンバ変数を定義する部分で、値を格納するための倍精度浮動小数点数valと誤差分散を格納するための倍精度浮動小数点数errがここで定義されている。なお、誤差分散は値の自乗のオーダーであるため、値の指数部の絶対値が極端に大きな値をとる場合にオーバーフローもしくは0への切捨てが発生する可能性がある。誤差は値に比べれば小さいため、オーバーフローは比較的起こりにくいと考えられること、オーバーフローが発生した場合は割り込みが発生して利用者に異常の発生が通知されることから、オーバーフローの弊害は比較的軽微であるといえる。一方で、0への切捨ては、オーバーフローに比べて起こりやすい上に切捨てが発生した際にも利用者がこれを知る手段をもたず、弊害はより大きいと考えられる。0への切捨てによる問題を回避するため、演算にゼロでない誤差分散をもつ変数が使用されており、かつ演算結果の誤差分散がゼロとなった場合に、演算結果の誤差分散を浮動小数点表示可能な最小値(Visual C++の場合、この値はDBL_MINで参照される)に置き換えている。
図2に示された例では、誤差分散の0への切り捨てが発生しうる箇所で、この修正を行う関数zero_chkを呼び出している。関数zero_chkの本体(14)は
図3に示した。
【0019】
図3はクラスRealに関する処理を行う関数の本体定義部分を示したもので、(14)はゼロでない誤差分散がゼロに切り捨てられることを防止するための関数zero_chkの定義、(15)は文字列を与えてクラスRealのオブジェクトを生成するためのコンストラクタ、(16)はクラスRealのオブジェクトを文字列に変換する関数ToStringの本体定義である。これらの関数定義に際しては、マイクロソフト社製のVIsual C++固有の関数を呼び出すことで記述を簡素化している。これらのVisual C++固有の関数に関しては、非特許文献2に解説がなされている。
【0020】
クラスRealを用いる際は、それが定数もしくは初期値を持つ変数であれば「gcnew Real("数値を表現する文字列")」の形で宣言し、初期値を持たない変数(たとえばx)であれば「Real^ x = gcnew Real」の形で宣言すればよい。また、誤差分散を数値として与える際には、「Real^ x = gcnew Real(値,誤差の標準偏差)」の形で宣言して双方の初期値を対として与える。ここで、「値」は変数の値を、「誤差の標準偏差」には誤差の標準偏差の具体的値を数値で記述する。通常は、誤差の標準偏差には有効桁の最下位の重みを与えればよく、たとえば小数部が2桁(0.01の位まで有効)の場合には誤差の標準偏差として0.01を与える。誤差の指標として使用する誤差分散は、コンストラクタの内部で標準偏差を自乗することにより得ている。Real型の変数に対する演算を行う際は、
図2の例では、Real型に対する四則演算子をそれぞれ定義しているので、通常の浮動小数点数に対する式と同様に、四則演算子を用いて式を記述すればよい。このようにすれば、プログラム作成者が意識することなく、値の演算と並行して誤差分散の演算を行う実行プログラムが自動的に形成される。
【0021】
クラスRealと同様の処理は、コンパイラが自動的に行うことも可能である。コンパイラに処理を委ねる場合には、ソースコード中に記述された定数の有効桁も、コンパイラが自動的に判別して誤差分散を与えることができる。
【0022】
演算結果に含まれる誤差を知ることは、それ自体にも演算結果の信頼性を高める上で意義があるが、さらにこの情報を用いて演算結果の精度を高めることも可能となる。数学的には同じ結果を得る演算式でも、異なる形で演算を行った際の演算誤差が異なるケースが多々ある。このような場合、双方の形式で演算を行い、得られた結果から誤差分散が最小の値を選べば、最も精度のよい結果を得ることができる。
【0023】
演算方法により誤差が異なる良く知られた例は、二次方程式の根の公式で、二次方程式の係数を次数の高い側からa、b、cとするとき、その根の公式は下に示す数式5の形が一般的に知られているが、b絶対値がa cに比べて大きい場合、一方の根に大きな誤差が含まれる。これを改善するには、一方の根を得る際に数式6の形に変形した式を用いることで精度が改善される。
【数5】
【数6】
【0024】
数式6は、bが正の場合に誤差の少ない結果を与えるが、bが負の場合は数式5が誤差の少ない結果を与える。すなわち、複数の演算方法がある場合にいずれが良い結果を与えるかは入力された数値に依存する。二次方程式の根の公式は比較的単純な形をしておりいずれの解法がよりよい結果を与えるかの判別は容易であるが、より複雑な演算式に対しては、このような判定を事前に行うことは困難である。本発明になる演算装置は、演算結果に含まれる誤差を知ることができるため、候補となる複数の演算式で演算を行って得られたそれぞれの結果から、誤差が最小となった結果を選択することで、最良の演算結果を得ることができる。
【0025】
次に、本発明をハードウエアとして構成した例を
図1に従い説明する。まず、二つのレジスタ(a)および(b)に演算の入力となる値とそれぞれの誤差分散を格納する。レジスタ(a)は、値を格納する部分(1a)、(2a)、(3a)および誤差分散を格納する部分(4a)、(4b)からなり、それぞれの部分は、符号ビット(1a)、指数部(2a)、(4a)および仮数部(3a)、(5a)から構成される。レジスタ(b)もレジスタ(a)と同様、(1b)から(5b)の各部分で構成される。それぞれのレジスタに格納された値は演算器(6)に導かれ各種演算に供され、演算結果はデータバス(8)に出力される。誤差分散演算器(7)には、それぞれのレジスタの誤差分散と値が入力され、演算の種別に応じた誤差分散が算出されてデータバス(8)に出力される。誤差分散の指数部は値の指数部に対するバイアスとして(4a)および(4b)に格納されており、これから誤差分散の指数部を得るために値の指数部(2a)および(2b)に対してベースの減算、シフト、および前記バイアスの加算が行われる。バス(8)に導かれた値と誤差分散の対は、そのままの形でレジスタもしくは主記憶装置に格納される。
【0026】
誤差分散の演算をハードウエアで行う利点は、値の演算と誤差分散の演算にそれぞれ専用の演算器を用いて同時に行うことで、演算が高速化される点である。値の演算は、今日では64ビット幅の浮動小数点形式で行うことが一般的であるが、誤差分散にはこれほどの精度は必要なく、仮数部を2ないし8ビット幅の符号なし整数、指数部を7ビット幅の符号付整数とすることで、実用上十分な精度で誤差分散を表現することが可能である。乗除算の誤差分散を求める際にはそれぞれの誤差分散に値の自乗を乗算する演算が含まれ、値の演算に比べて複雑な演算が必要となるが、桁数が少ないことで個々の演算の所要時間は短く、値の演算に近い所要時間で誤差分散の演算を並行して行うことができる。なお、誤差分散の演算をハードウエアで行う場合にも、入力数値の有効桁の判定や有効桁のみを出力する処理の部分は、ソフトウエアによって構成することが簡便であり好ましい。
【0027】
誤差分散は値の自乗に対応することから、その指数部の絶対値は大きな値をとり、オーバーフローや0への切捨てが生じるリスクがある。
図1には、誤差分散の指数部を、誤差分散固有の指数部の値と値の指数部の二倍とを加算して与えることで、このリスクを軽減した例を示している。
図1に示す例では、値の浮動小数点表現にIEEE754に規定された倍精度浮動小数点表現を用いることを前提としている。この場合、指数部には1023の下駄を履いた値(baseを加算した値)が格納されている。これを調整するためにbaseの減算が行われる。次に、誤差分散は自乗形式で表されているため、値の指数部を二倍して誤差分散の指数部にあわせる。これを誤差分散固有の指数部(4a)に加算することで誤差分散の指数部を形成している。図には示していないが、演算結果の誤差分散の指数部は、誤差分散の演算結果から値の指数部の二倍を差し引いた値を出力する。
【0028】
IEEE754に規定された浮動小数点表現は、常に仮数部の最上位が1となるよう規格化を行っており、仮数部のいずれのビットが有効桁であるかは一概には定まらず、誤差分散固有の指数部(4a)および(4b)は値の仮数部の有効桁位置によって変動する。浮動小数点表現として、仮数部の有効桁位置を常に一定に保つ浮動小数点表現を採用すれば、誤差分散固有の指数部はほぼ一定となり、値の指数部から算出される指数部を誤差分散の指数部とし、誤差分散固有の値は仮数部(5a)および(5b)のみとすることも可能である。
【0029】
図4は
図1に示した演算装置にこの改良を施した例であり、値の指数部(2a)を二倍したものを誤差分散の指数部として用い、誤差分散の指数部を格納するレジスタを省略している。この手法においては、値の仮数部の有効桁が所定の位置となるよう、値を演算する際に正規化が行われる。
図4に太線で示した誤差分散の演算器(7)から値の演算器(6)に向かうパスはこのためのものであり、演算された誤差分散の仮数部が所定の範囲に収まるように2nビットのシフトを行うと共に、nを値の演算器に通知して値のシフトと指数部の調整を行っている。なお、
図4には、値の指数部も仮数部も符号付数で表現することで、値の符号ビット(1a)および(2a)と指数部へのbase加算を省略した例を示している。