FPGAを使った数値演算回路実現の勘所(3) ―― 浮動小数点演算器の構成を考える Part 1
●IEEE 754として単精度形式を規定
先に述べた「データの互換性」を保つため,IEEE 754にて,符号,指数部,仮数部の統一フォーマットが取り決められています.ハードウェアで浮動小数点を扱ったことがなくても,単精度,倍精度という言葉を耳にしたことがある方は少なくないでしょう.単精度の場合のフォーマットを図1に示します.
図1 IEEE 754単精度の浮動小数点フォーマット
全体で32ビットとなるように,符号,指数部,仮数部が割り当てられており,各部は以下のような取り決めになっています.
1) 符号
正の場合に0,負の場合に1となります.
2) 指数部
8ビットで表現され,通常の状態では-126~+127が使用され,ここに127のオフセットが加算されて,1~254(正数)として表わされます(これを「ゲタばき表現」という).従って,この値から127を減算すれば,2の補数に変換できます.0と255には少々特殊な状態が割り当てられています.表1を参照してください.ゲタばき表現とする理由は,CPU演算において大小比較を楽にすることにあります.ハードウェアとして特別なメリットがあるわけではありません.CPUだってハードウェアでしょ,と言われると困るのですが....
表1 指数部と仮数部の状態割り当て
3) 仮数部
23ビットで表現されますが,小数部のみを表していて,最上位の整数部1ビットは含まれていません.適正な状態で使用されれば最上位の整数部は必ず1となっており,それなら表示しなくても良いでしょう,という考え方です.表示されない1は「暗黙の1」と呼ばれます.この状態(指数部=1~254,仮数部の整数部=1)を正規化数といいます.それ以外の状態の割り当てについては,やはり表1を参照してください.
仮数部の最小位ビットをulp(unit in the last place)と呼び,演算の精度を表す単位として用いられます.固定小数点ではLSBは決められた特定の重みを示すのですが,浮動小数点では指数部によって仮数部の最小位ビットの重みが変化します.あくまでも有効けたの最小位を単位として精度を表しており,実際の大きさは問わないわけです.
ここで,表1の中の用語について解説しておきます.
「不正規化数」(「非正規化数」と訳される場合もある)は正規化数で表現できる最小値より小さく,非0の数を示します.演算でアンダフローが発生した状態です.注意しなければならないのは,このときのみ指数部の表わす0はゲタを外した-127ではなく,-126であるという点です.正規化数で表現できる最小値より小さな数を,上位に0を詰めて有効けたを犠牲にすることで表現しています.暗黙の1はなくなり,仮数部の整数部は0となります.
「±無限大」は演算上でオーバフローが発生した状態です.正規化数としては表現できなくなるので,特定のコードを割り当てて表現します.オーバフローのフラグと考えればよいでしょう.
「NaN」は非数と呼ばれ,無効な演算を行った場合の結果を表わす状態です.例えば0÷0や∞-∞などがそれにあたります.この状態に対してさらに演算を行った場合は,NaNしか得られなくなります.
●正規化で演算結果の範囲が限定される
正規化された数によって得られる恩恵は大きいものがあります.最上位の整数部が必ず1であると分かっているので,演算結果の値の範囲が限定的になります.例えば仮数部の演算に着目すると,乗算では1≦積<4,除算では1/2<商<2となります.また,回復法による除算では,減算を開始するけた位置を最初から有効なけたに合わせられるので,無駄なステップを排除するのに有効です.
逆に不正規化数では,こうした恩恵は受けられなくなります.加えて,有効けたを失っているので,この後の演算結果は精度面で適正ではありません.扱いの面倒な数になります.このため,ハードウェアでは不正規化数は扱わないとする場合が多々あります.規格で認められているからといって,それが有用か否かは別の話,といったところでしょうか.
●丸めモードは4種類
精度を適正に保つには,演算後の丸めが重要です.IEEE 754では四つの丸めモードが規定されています.
- 切り上げ(+∞方向への丸め)
- 切り下げ(-∞方向への丸め)
- 切り捨て(0方向への丸め)
- 最近点への丸め
最初の3モードについては,読んで字のごとくです.
「最近点への丸め」は0捨1入にきわめて近い考え方なのですが,若干の違いがあります.ulpより下位のけたが1/2 ulpより大きければ切り上げ,小さければ切り捨てるところまでは同じで,1/2 ulpに等しいときの操作がulpの値によって異なります.ulp=1のときは切り上げ,ulp=0のときは切り捨てになります.最下位より1けた下が1/2 ulpに等しいときは,ulpの0と1の生起確率が等しいであろうという前提で,切り捨てと切り上げを等確率で得るための措置です.精度を保つ上で,最も適した方法です.
●G,R,Sの3ビットで精度を保つ
「最近点への丸め」モードを実施するにあたり,ulpより下位の大きさを判断するビットが必要になります.それが以下の三つのビットです(図2).
- ガード・ビット(Guard Bit,以下Gビット)
- ラウンド・ビット(Round Bit,以下Rビット)
- スティッキ・ビット(Sticky Bit,以下Sビット)
図2 G,R,Sビットのけた位置
Gビットは1/2 ulpの重みを持つビットで,先に述べたulpより下位のけたの1/2 ulpに対する大小を決める境界の役目を持っています.Rビットは1/4 ulpの重みを持つビットで,準Gビット的な役割になります.Sビットはそれ以下のビットのORを取った値で,ulpより下位のけたが1/2 ulpに等しいか否かを判定するのに用います.
実際にどう使うかについては,参考文献(1)に説明があるので,参考にしてください.