1.6.5 浮動小数点数演算 / 非公式訳

浮動小数点数同士の加算は、指数部の小さいほうの浮動小数点数の假数部を右シフトして両者の指数部を同じにしてから假数部同士を加算する(参考: 現実的なCプログラミング (NUTSSHELL HANDBOOKS), pp.318-319)。
10進数の例:
1.23E10 + 1.23E12
= 1.230E10 + 1.230E12 // 保護桁を加える。
= 0.012E12 + 1.230E12 // 指数が小さいほうの数の假数部を右シフトして両方の指数を揃える。
= (0.012 + 1.230)E12 // 加算する。
= 1.242E12 // 正規化する(小数点の左に非ゼロが1桁だけくるように指数部を調整すること。scientific notationにすること)。
≒1.24E12 // 保護桁を丸める。

残念ながらfloat_pkgライブラリーはQuartus Prime Liteでは使えず、pp.263-264のexampleは試せなかった。

関連: float (単精度浮動小数点数)の内部表現 -

pp.24ff.

非公式訳:
1.6.5 浮動小数点数演算
浮動小数点(FP)数表現およびその操作はIEEE 754-2008規格に定義してあります。以下の説明はそれに基づいたものです。

浮動小数点表現
IEEE 754規格のなかで特によく使われている2つを図1.27に示します。1つめの形式は32ビット用であり、符号部(S)が1ビット、指数部(E)が8ビット、假数部(F)が23ビットという構成です。2つめの形式は64ビット用であり、符号部(S)が1ビット、指数部(E)が11ビット、假数部(F)が52ビットという構成です。

ただし表1.3にまとめたように、この表現にはいくつか制約があります。実際の0は存在しないため、表の1行目に示したように、指数部、假数部ともに0で埋めるという特殊な形で0を表現します。無限大も存在しないため、表の2行目に示したように、指数部は1で、假数部は0で埋めるという形で無限大を表現します。一番下の行が正規化数の処理です。これを見ると分かるように、指数Eは1 ≦ E ≦ MAX-1の範囲になければなりません。MAX=2EwidthであるためEmax=MAX-1=2Ewidth-2、Ewidthは指数部のビット数です。

浮動小数点数から整数への変換
FPベクタの10進数値(dec)は下式で求まります。オフセット係数BIAS=Emax/2=2Ewidth-1-1です。
 dec=(-1)S(1+F)2E-BIAS

図1.27の場合は以下の式が得られます。
32ビット規格: dec=(-1)S(1+F)2E-127、Eは1≦E≦254
64ビット規格: dec=(-1)S(1+F)2E-1023、Eは1≦E≦2046

上の式を適用すると、32ビット規格で表現できる10進数値の最小値と最大値は、0と無限大とを除けば次のようになります。

最小値decmin=(1+0)21-127=2-126
最大値decmax=(1+0.99...)2254-127=(2-2-Fwidth)2127
Fwidthは假数部のビット数です。上限は2128に極近い値(無限大に相当)です。

2ビット値の例を2つ、図1.28に示します。それぞれ以下の10進数値に相当します。
(a) S=0, E=129, F=1/4, BIAS=127; dec=(-1)0(1+1/4)2129-127=5
(b) S=1, E=127, F=1/2, BIAS=127; dec=(-1)1(1+1/2)2127-127=-1.5

整数から浮動小数点数への変換
下の例は、整数からFP表現への変換方法を示したものです。
0.75の場合:
0.75=1/2+1/4
  =3/4
  =3・2-2
  =0b11・2-2
  =0b1.1・2-1
したがって
S=0,
F=0b1000...0, (訳註: 暗黙の1があるため、0b11000...0にはならない)
E=0b0111_1110 (E-BIAS=-1であるためE=126)
 
-2.625の場合:
2.625=2+1/2+1/8
   =21/8
   =21・2-3
   =0b10101・2-3
   =0b1.0101・21
したがって
S=1,
F=0b01010...0, (訳註: 暗黙の1があるため、0b10101...0にはならない)
E=0b1000_0000 (E-BIAS=1であるためE=128)

浮動小数点拡張

図1.29に浮動小数点拡張の原理を示します。ここでは、白で示した指数部を4ビットから7ビットへ拡張子、符号ビットと同じくグレーで示した假数部を2ビットから4ビットへ拡張しています。a2~a-2はb2~b-2へそのまま移します。拡張する假数部には0を埋めます。ただし指数部は、 b6=a3、 b5=b4=b3=a3' という若干のデータ操作が必要です(dec=(-1)^S(1+F)2^(E-BIAS)であるので、値を同じに保ったまま旧ベクタから新ベクタへ拡張するためには、E2=E1+BIAS2-BIAS1という関係が満足されなければならない)。

表1.3に示したように、全ビットが1で埋まった指数部は±∞かNaNかいずれかです。元のベクタがそうなっている場合(図1.29のANDゲートで判定する)は、拡張後のベクタの指数部も1で埋めなければなりません(この処理はマルチプレクサーで実行する)。ここまで述べたルールに従った浮動小数点拡張の例を下に示します。

a=(1)(0011)(01)→
b=(1)(0111011)(0100)
註: a=b=-1.25・2-4

浮動小数点数の切り捨てと丸めと
浮動小数点数値のをリダクションするときは、図1.29とは逆の操作が必要です。その際の問題は、b6=a3、b5=b4=b3=a3' という関係を満足しなければならないことです(他のベクタサイスでも同様)。そうでないと、元の値が小さくなりすぎて、あるいは大きくなりすぎて、リダクション後のビット数に収まりきらなくなるからです。小さすぎる場合は、リダクション後のベクタをE=00...0、F=00...0で埋めなければならず、これは0に相当します(表1.3)。大きすぎる場合は、リダクション後のベクタをE=11...1、F=00...0で埋めなければならず、これは無限大に相当します。

浮動小数点数リダクションは、まず假数部の一部を丸めてビット数を減らします。そのあと、前述した式を使うか、1または1を直接動かすかして指数部のビット数を減らします。たとえば
a=(0)(0111011)(0100)を
b=(0)(b3b2b1b0)(b-1b-2)へ
ビット数を減らす場合はまず假数部を切り捨てて丸めます。すると(0)(0111011)(01)という結果が得られます(丸めは不要でした)。a5=a4=a3=a6' であるため、b3=a6と割り当てて、a5a4a3は削除します。すると最終結果は(0)(0011)(01)となります。a=(1+0.25)259-63とa=(1+0.25)23-7とが実際に同じであることに注目してください。

IEEE 754規格には5つの丸めオプションが定義してあります。(略)

詳しい例を表1.4に示します。bの最小値、最大値はそれぞれ
bmin=(1+0)2Emin-BIAS
  =21-7
  =2^-6

bmax=(1+3/4)2Emax-BIAS
  =7/4・214-7
  =7/8・28

表の1列目にaの値として4つ示しました。順番に増やしていっています。最初の2つはbminより小さく、最後の2つはbmaxより大きい。最初の手順は、假数部の一部を切り捨てて丸めることです。そうして得られた値を第2列(a)に示します。最初の値はbminよりも小さいままであり、b=0という結果になります。しかし2つめの値は、切り捨てて丸めると値が増えて、もはやbminよりも小さな値ではなくなり、b=aが正しい値となります。3つめの値を切り詰めて丸めてビット数を減らすと、もはやbmaxよりも大きくはなくなり、これもやはりb=a*が正しい値となります。最後の値はbmaxよりも大きいままであり、b=∞となります。

浮動小数点数の加算

このセクションの最後に、浮動小数点数の加算について説明します。
手順1: 指数部が違っている場合は、指数部の小さいほうの数の假数部を右シフトして指数部を同じにします。
手順2: 假数部を加算します。値が負である場合は、その2の補数を足し合わせます。加算結果のMSBが1の場合、和は負数であり、S=1です。その場合、得られた結果に2の補数化の逆の処理を適用して正の値に戻さなければなりません。浮動小数点表現では、Sを除き、負数も正数もビット値だけを見ればまったく形で同じ表現されるからです。
手順3: 結果を正規化(科学的記数法)にし、指数がオーバーフローしていないかどうかを確かめます。指数が許容範囲を外れている場合は表1.3のルールを適用します。
手順4: 假数部が規定の幅を超えている場合は、前述の手順による切り捨て、丸めの必要になることがあります。必要ならもう一度正規化します。

例として0.75+2.625について考えます。指数部は4ビット、したがってBIAS=7、假数部はわずか2ビットとします。すでに見たように
0.75=0b1.1・2(-1)、
2.625=0b1.0101・21
です。
手順1: 0b1.1・2-1→0b0.011・21
手順2: 0b1.0101+0b0.011=0b1.1011。ゆえに0.75+2.625=0b1.1011・21
手順3: 結果はすでに正規化されていて、指数部E=1+BIASは許容範囲1~14に収まっています。
手順4: 假数部を2ビットに縮めなければなりません。表1.2から、切り詰めた假数部の末尾ビットに1を加えなければならないことが分かります。つまり0b1.10+0b0.01=0b1.11ということです。したがって最終結果は0.75+2.625=0b1.11・21です。そこから以下の浮動小数点数が得られます。
S=0
E=0b1000
F=0b11 (訳註: 暗黙の1がある)
すなわち3.5です。正確な値は0.75+2.625=3.375です。

その他の例を以下に示します。(略)