浮動小数点数
この節はパターソンらの記述に基づく。
実数は0以上かつ1以下のような有限の範囲でも、無限個の値(種類)が存在するため、コンピュータでは妥当なビット数で有限個の値(種類)の近似値で扱う必要がある。
実数-1/3は無限小数となるが、有限桁の小数で近似値を表記できる。下の例では10進数での4桁としている。
-1/3
-1 x 0.33333333333333...
-1 x 0.3333 x 10
-1 x 3.333 x 10
下の2つの表記は科学記数法 (scientific notation) とよばれ、小数点より左側の整数部分を1桁とする。 科学記数法のうち、左側の1桁を0以外(10進表記では1から9)にしたものを、正規化数 (normalized number) とよび、 一番下の表記が該当する。
実数-1/3はまた、有限桁2進数の小数でも、近似値で表記できる。下の例では2進数17桁としている。
-1/3
-1 x 0.01010101010101010101010101010101.
ここで、2 = 2、4 = 2、16 = 2、256 = 2 である。このように 0 や ±∞ を含む区間は「二重指数分割」する。
0 000000 = 0
0 000001 = 0.0000152587890625 (1/65536)
0 000010 = 0.00390625 (1/256)
0 000011 = 0.015625 (1/64)
0 000100 = 0.0625 (1/16)
0 000110 = 0.125 (1/8)
0 001000 = 0.25 (1/4)
0 111000 = 4 (2)
0 111010 = 8 (2,3=(2+4)/2)
0 111100 = 16 (2)
0 111101 = 64 (2,6=(4+8)/2)
0 111110 = 256 (2)
0 111111 = 65536 ~ ∞
このように、区間の両端の比が2より大きい場合は、「等比分割」する。
以上のような操作の結果として、指数部が0以上の場合は
"0 10" = 0
"0 11(1がn個)0(n個のビット列Bn)" = 1Bn (ガンマ符号の桁数出力とその後の"1"をビット反転したもの)
指数部が0未満の場合は
"0 01" = 上述の"0 10"の符号ビット以外をビット反転させたもの = 2進数"0"をビット反転させたもの = −1
"0 00(0がn個)1(n個のビット列Bnをビット反転させたもの)" = 上述の"0 11(1がn個)0(n個のビット列Bn)"の符号ビット以外をビット反転させたもの = 2進数"1Bn"をビット反転させたもの = −(1Bn)−1
)
特に単精度において、前世代機のIBM 7094(全部で36ビット)よりも桁数を減らした(32ビット)ことと相まって精度が大きく損なわれた。その他にも問題があり、ユーザグループであるSHAREから改善提案が出され、その多くを受け入れて多大なコストのかかる改修をおこなったほどであり、これを記憶しているIBMの古参社員は「身の縮む思い」をおぼえているという。
また、計算対象の数値がベンフォードの法則に従って分布していた場合、計算対象として精度の低い数(仮数部の最上位4ビットが0b0001)の現れる確率は1/15にはならず、もっと高い。
IBM方式の単精度浮動小数点数では、符号部1ビット、指数部7ビット、仮数部24ビットで表現されている。各部は次のように定義されている。
符号部は、0を正、1を負とする
仮数部は、1未満の16進小数とする
指数部は、16を基数とした指数に64をバイアスした値で表す
符号部は仮数の符号を表す。 指数部は−16~−16と16~16の範囲が表現できる。
IBM方式は、IBM社がSystem/360で導入し、以後同社の標準としてSystem/370などのメインフレームで使った方式である(System/390では、従来形式のサポートは残すもののIEEE 754を使用するよう改めた)。指数部が2の冪ではなく16の冪を表すという特徴がある。この方式は、より大きな範囲を少ないビット数の指数部で表すことができ、そのぶんのビットを仮数部の桁数に使うことで精度も確保できるように一見思える。しかし、仮数部にケチ表現を使うことができず、さらに指数部の変化の前後で、仮数部のLSBが表現する値の刻み幅が16倍変化するため、2べきの場合に比べて最悪の場合には2進で3ビット分の精度が損なわれるため、一般には大成功であったと評されたSystem/360の設計において良くなかった点の一つとして挙げられる。(浮動小数点数の加減算の際に必要となる仮数部のシフトが4ビット単位となるのでシフト回数が減ることで演算が15%程度高速になる利点も16進数が採用された理由であった。
浜田穂積が提案した方式で、Universal Representation of Real numbersの意でURRと名付けられている。−∞ ~ 0 ~ ∞ の区間を、次のように分割しながら、二進法による表現に対応付ける、というのが基本的な考え方で、「符号と絶対値」形ではなく、浮動小数点の表現としては比較的珍しい2の補数の形をしている。
100 = −∞
101 = −2
110 = −1
111 = −0.5
000 = 0
001 = 0.5
010 = 1
011 = 2 ~ ∞
ここで±1の前後は、区間の両端の比が2なので、指数部の表現は終わったとみなすことができ、残りの桁は仮数部のように扱う(±1の前後は、以後は1/2で等差分割する)。次のように分割を続ける。
1000 = −∞
1001 = −4
1010 = −2
1011 = −1.5
1100 = −1
1101 = −0.75
1110 = −0.5
1111 = −0.25
0000 = 0
0001 = 0.25
0010 = 0.5
0011 = 0.75
0100 = 1
0101 = 1.5
0110 = 2
0111 = 4 ~ ∞
以降は、符号ビットが0である0 ~ 0.5 と 2 ~ ∞ の区間に絞って説明する。
0 00000 = 0
0 00001 = 0.00390625 (1/256)
0 00010 = 0.0625 (1/16)
0 00100 = 0.25 (1/4)
0 01000 = 0.5 (1/2)
0 11000 = 2
0 11100 = 4
0 11110 = 16
0 11111 = 256 ~ ∞