丸め

符号付き固定小数点数どうしの積を考えてみましょう。1.15形式の符号付き固定小数点数を二つ掛け合わせると、積は1.30形式になります。なぜなら、小数点より左の1ビットは符号ビットなので掛け合わせてもビット数は増えません。また、右側の15ビットどうしを掛け合わせると有効ビット数は30ビットになります。DSPはこの形式の商の一番右側に0を追加して1.31形式に変換します。ここまでは誤差は一切混入せず、また、16ビットDSPならちょうど2ワードで表現できます。

問題はここから先です。16ビットDSPで高速に実行するには16ビットオペランドを使うしかありません。そこで、1.31形式の数を1.15形式に変換しなければなりません。幸い、固定小数点数では小数点の右側のビットを切り捨てても、精度が悪化するだけで数値の大きさ自身はほとんどかわりません。となれば、問題はいかに精度を悪化させずに変換させるかということになります。

切り捨ては最も簡単な方法です。これは1.31形式の下位16ビットがすべて0であるとみなしてばっさり切り捨てる方法で、符号付き数の場合は「負の無限大への切り捨て」と呼ばれます。このような呼び方をするのは切捨てによって値が負の無限大の方向にずれるからです。切捨てにはこの他に0への切り捨てがあり、この場合には正の数も負の数も0に向かってずれます。切捨てによって発生する誤差の絶対値は、1LSB未満です。ここでいう1LSBとは、上位16ビットのLSBであることに注意してください。

切捨てよりも精度が高い丸めの方法に四捨五入があります。これは我々が小学校の算数で習った方法で、2進数の場合は0捨1入となり。実装の仕方も簡単で、切り捨てられる部分の最上位ビットのみ見て1ならば切り上げ、0ならば切捨てとなります。この方法では、誤差の絶対値は0.5LSB以下になります。

我々は四捨五入を使い慣れているためこれが一番よい方法のように感じます。しかしながら、この方法には統計的偏りという欠点があります。問題が起きるのは丸められる数がちょうど中間値の場合です。例えば、下位16ビットを丸める場合を考えてみましょう。この部分が0x8000の場合、切り上げても切り捨てても誤差の絶対値は等しく0x8000です。ところが、四捨五入方式ですと必ず切り上げが起きてしまいます。このため、統計的に見るとかすかにですが偏りが生じることになります。

そこで四捨五入の改良が使われます。これは「丸められる数がちょうど中間値の場合には残った有効数字の最下位桁が偶数になるように丸める」という方式です。これはJISで規定されていることから10進数ではJIS丸めと呼ばれます。2進数の場合にはRound to nearst even、Convergent Roundingなどと呼ばれます。日本語の訳は一定していないようですが、最近偶数丸め、あるいは収束丸めといった訳語があるようです。この方式は数値演算の分野で広く使われており、DSPでは普通に使われるほか、IEEEの浮動小数点数標準でも採用されています。

例を見てみましょう。0X1234_8000という32ビット数があり、下位16ビットを丸めるとします。通常の0捨1入であれば切り上げて、0x1235となります。しかし、最近偶数丸めの場合には切り上げると最下位が「5」と奇数になるため、切り下げて0x1234となります。別の例として0X1233_8000の場合は、0捨1入の場合も最近偶数丸めの場合も結果は0x1234となります。

このように一口に丸めといっても種類があり、その性質もさまざまです。DSPで使われている丸め方式は複雑に見えますが、それなりの理由があるのです。

⇒次はABS(-1)

2191空挺団 | プログラム | EZ-KIT | こぼれ話 | アーキテクチャー | 命令 | レジスタ | DSP掲示板 | FAQ |