IEEE 浮動小数点表現
Microsoft Visual C++ は、IEEE 数値規格に準拠しています。実数には、3 種類の内部表現があります。Visual C++ では、real*4 および real*8 を使用しています。real*4 は float で宣言します。real*8 は double で宣言します。32 ビット Windows プログラミングでは、long double 型は double 型に変換されます。ただし、アセンブリ言語と使用すると、real*10 データ型による計算もできます。
値は、次の形式で格納されます。
値 |
形式 |
---|---|
real*4 |
符号ビット、指数 8 ビット、仮数 23 ビット |
real*8 |
符号ビット、指数 11 ビット、仮数 52 ビット |
real*10 |
符号ビット、指数 15 ビット、仮数 64 ビット |
real*4 形式と real*8 形式では、仮数の先頭にメモリに格納されない 1 があると仮定しています。したがって、23 ビットまたは 52 ビットしか格納されなくても、実際の仮数は 24 ビットまたは 53 ビットになります。real*10 形式では、このビットも実際に格納されます。
指数は、その最大値の 1/2 でバイアスされます。したがって、格納された指数の値からそのバイアス値を引くと、実際の指数の値になります。格納された指数の値がバイアス値より小さい場合、実際には負の値の指数になります。
指数は、次のようにバイアスされます。
指数 |
バイアス |
---|---|
8 ビット (real*4) |
127 |
11 ビット (real*8) |
1023 |
15 ビット (real*10) |
16383 |
これらの指数は 10 の累乗ではなく、2 の累乗です。つまり、8 ビットで格納される指数は、最高 127 になります。real*4 の実際の上限である 2**127 の値は、10**38 とほぼ等しくなります。
仮数は、1.XXX... という形式の 2 進小数として格納されます。.この小数の値の範囲は、1 以上 2 未満です。実数は、必ず正規化形式で格納されます。つまり、仮数は左シフトされ、仮数の最上位ビットが必ず 1 になります。したがって、real*4 形式と real*8 形式では最上位ビットを常に 1 と仮定し、それを格納しません。先頭の 1 のすぐ右側には、10 進ではなく 2 進小数点が仮定されます。
したがって、各種サイズの形式は次のようになります。
書式 |
バイト 1 |
バイト 2 |
バイト 3 |
バイト 4 |
... |
バイト n |
---|---|---|---|---|---|---|
real*4 |
SXXX XXXX |
XMMM MMMM |
MMMM MMMM |
MMMM MMMM |
|
|
real*8 |
SXXX XXXX |
XXXX MMMM |
MMMM MMMM |
MMMM MMMM |
... |
MMMM MMMM |
real*10 |
SXXX XXXX |
XXXX XXXX |
1MMM MMMM |
MMMM MMMM |
... |
MMMM MMMM |
S は符号ビット、X は指数ビット、M は仮数ビットを示します。最上位ビットは、real*4 形式と real*8 形式では省略され、real*10 形式のバイト 3 では "1" として存在しています。
2 進小数点を正しくシフトするには、まず指数のバイアスを除き、次に 2 進小数点を該当するビット数だけ右側または左側に移動します。
例
real*4 形式の例を次に示します。
この例では、符号ビットは 0、格納された指数は 128 (2 進の 100 0000 0)、つまり 127 + 1 になります。格納された仮数は、先頭の 1 と 2 進小数点が仮定された、(1.) 000 0000 ... 0000 0000 になります。したがって、実際の仮数は 1 になります。
SXXX XXXX XMMM MMMM ... MMMM MMMM 2 = 1 * 2**1 = 0100 0000 0000 0000 ... 0000 0000 = 4000 0000
符号ビットが設定されている点を除き、-2 の場合も同じになります。このことは、すべての IEEE 形式の浮動小数点数に当てはまります。
-2 = -1 * 2**1 = 1100 0000 0000 0000 ... 0000 0000 = C000 0000
仮数は同じで、指数が 1 増えています。バイアスされた値は 129、つまり 2 進の 100 0000 1 になります。
4 = 1 * 2**2 = 0100 0000 1000 0000 ... 0000 0000 = 4080 0000
指数は同じで、仮数が 1/2 大きくなっています。つまり、(1.) 100 0000 ...0000 0000 (1 + 1/2 の 2 進小数点表現) になります。小数桁の値は、1/2、1/4、1/8 などになります。
6 = 1.5 * 2**2 = 0100 0000 1100 0000 ... 0000 0000 = 40C0 0000
指数は同じで、仮数が 2 よりも 1 小さい値、つまり 127 (2 進の 011 1111 1) になっています。
1 = 1 * 2**0 = 0011 1111 1000 0000 ... 0000 0000 = 3F80 0000
バイアスされた指数は、126 (2 進の 011 1111 0) になります。仮数は、(1.) 100 0000 ... 0000 0000、つまり 1 + 1/2 になります。
.75 = 1.5 * 2**-1 = 0011 1111 0100 0000 ... 0000 0000 = 3F40 0000
仮数の 1/4 を表すビットが設定されている点を除き、2 とまったく同じになります。
2.5 = 1.25 * 2**1 = 0100 0000 0010 0000 ... 0000 0000 = 4020 0000
1/10 は、2 進では反復小数です。仮数はわずかに 1.6 より小さくなり、バイアスされた指数は 1.6 を 16 で割ることを示しています。つまり、2 進の 011 1101 1、10 進の 123 になります。実際の指数は 123 - 127 = -4 であり、乗数が 2**-4 = 1/16 であることを示しています。格納された仮数は最後のビットで丸められているので表現できない値ですが、最も近い値になっています。1/10 や 1/100 を 2 進で正確に表すことができないのは、10 進で 1/3 を正確に表せないのと同じです。
0.1 = 1.6 * 2**-4 = 0011 1101 1100 1100 ... 1100 1101 = 3DCC CCCD
0 = 1.0 * 2**-128 = all zeros--a special case.