浮動小数点数について
木村巌
∗ 2004
年7
月7
日1 浮動小数点数
1.1
浮動小数点数表示の一般論浮動小数点数とは、実数
x
を計算機の上で近似するための方法である.自然 数b
を固定し、これを基数とよぶ.実数x
を、符号部、指数部、仮数部に分け て考える.符号部は
+
または−
のみ.指数部というのは、1≤ b
−e|x| < b
となるようにe
を取った時のb
e, e
を指数という.仮数部というのはb
−e|x|
のことをいう.仮数部を
b
進表記して、xの仮数部= f
0b
0+ f
1b
−1+ · · · + f
pb
−p, 0 ≤ f
i< b
と書いた時、pを桁数という.例
1:
基数10
について、10進の−123.45
を表現すると、−123.45 = −1 × 10
2× (1 + 2 × 10
−1+ 3 × 10
−2+ 4 × 10
−3+ 5 × 10
−4).
これを、「-1|2|12345」のように表すと、指数部に
10
進1
桁、仮数部に10
進5
桁を用いた浮動小数点数表示となる.例
2:
基数10
について、10進の+0.000987
を表現すると、+0.000987 = +1 × 10
−4× (9 × 10
−1+ 8 × 10
−2+ 7 × 10
−3).
これを、「1|-4|987」のように表すと、仮数部に
10
進5
桁を用いた浮動小数点 数表示となる.例
2
では、指数部に負の数が現れているが、このような状況に対応するため に、指数部に一定の数を足し(バイアスという)、常に正にとることがおおい.例えば今の場合、バイアスを
4
とすれば、指数部を10
進1
桁の範囲で0.000987
が、「1|0|987」のように表現できる.∗
2004
年度前期・プログラミング演習I
資料一般に、基数
b
に関する浮動小数点数表示は、x = s × b
e× X
pk=0
f
kb
−k,
s
が符号(+または−)、b
は基数で(2,8, 10, 16
のいずれかであることが多い)、e
が指数、pは桁数、fkはそれぞれ各桁を表す数字(0≤ f
k< b)、という形に
なる.したがって、基数、指数の桁数、仮数部の桁数によって、一つの浮動小数点 数表示が表現できる数の範囲と、その精度が定まる.
例
3:
基数10,
指数の桁数1,
バイアス4,
仮数部の桁数5
とすると、この浮動小 数点数表示で表現できる最大の値は、「1|9|99999」、即ち+1 × 10
9−4× (9 × 10
0+ 9 × 10
−1+ 9 × 10
−2+ 9 × 10
−3+ 9 × 10
−4)
= 10
5× (9.9999) = 99990.
問
1:
上の例3
の浮動小数点表示で表現できる最小の正の値、ならびに最小の値 を求めよ.次に、浮動小数点数表示の精度について考えよう.上記の例のように、基数
10,
指数の桁数1,
バイアス4,
仮数部の桁数5、の浮動小数点数表示で、
「1|9|99999」は 999990
であった.同様の計算で、「1|9|99998」は999980
であるこ とがわかる.つまり、仮数部の最後の1
桁を1
減らすと、実数としては10
の差 が出る.「1|
8
|99999」と「1
|8
|99998」とについて同じことを考える.
「1|8
|99999」
は
99999
であり、「1|8|99998」は99998
である.つまり、指数が8(バイアス 4
があることに注意)のときは、仮数部の最後の1
桁の1
の差が、実数としても1
の差となる.更に、「1|7|99999」と「1|7|99998」とについて同じことを考える.「1|7
|99999」は
9999.9
であり、「1|7|99998」は9999.8
である.つまり、指数が7
のときは、仮数部の最後の1
桁の1
の差が、実数としては0.1
の差となる.まとめると、二つの浮動小数点数
a, b
があり、その指数部は等しいとする.指 数が大きい場合は、a, b
の仮数部の差は、a, b
の大きな差となる.また、指数が小 さい場合は、a, bの仮数部の差は、a, b
の小さな差となる、ということがわかる.1.2
基数が2
の場合の浮動小数点数表示:IEEE754
基数を
2,
符号に1bit,
指数にm bit,
仮数にn bit
使うとすると、全体の幅は1 + m + n bit
になる.最初の1
は常にあるように指数部を調節するのだから、記憶する必要がない事に注意する(ケチ表現).
更に、基数
2
に関する浮動小数点数表示に関しては、IEEE754という国際規 格が存在し、現在のほとんどのコンピュータで採用されている.例えば、基数
b = 2
で全体の幅が32bit(=8bytes)の浮動小数点数が、指数
部に8bit,
仮数部に23bit
用いるものとすると、x = (−1)
s× 2
e× Ã
1 + X
23k=1
f
k2
−k! ,
s = 0, 1, e
は−126 ≤ e ≤ +127
を満たす自然数1.
指数のバイアスは127. C
言 語のfloat
はこのようになっている.同様に、基数
b = 2
で全体の幅が64bit
の浮動小数点数が、指数部に11bit,
仮数部に
52bit
用いるものとすると、x = (−1)
s× 2
e× Ã
1 + X
52k=1
f
k2
−k! ,
s = 0, 1, e
は−1022 ≤ e ≤ +1023
を満たす自然数2.
指数のバイアスは1023. C
言語のdouble
はこのようになっている.例
4: float
型で0.5
がどのように表示されるのか考えてみよう.0.5 = (−1)
0× 2
0× 1 × 2
−1= (+1) × (2
−1) × (1 + 0 × 2
−1+ · · · + 0 × 2
−24).
バイアスは
127
であるから、指数は126 = (01111110)
2である.また、ケチ表 現(仮数部の2
0の桁は必ず1
なので記録する必要がない)を考えれば、0.5 =「0|01111110|000000000000000000000000」である.
例
5:
同様に、float型で1.75
がどのように表示されるのか考えてみよう.1.75 = (−1)
0× 2
0× (1 × 2
0+ 1 × 2
−1+ 1 × 2
−2)
= (+1) × (2
0) × (1 + 1 × 2
−1+ 1 × 2
−2+ 0 × 2
−3+ · · · + 0 × 2
−24).
バイアスは
127
であるから、指数は127 = (01111111)
2である.また、ケチ表 現(仮数部の2
0の桁は必ず1
なので記録する必要がない)を考えれば、1.75 =「0|01111111|110000000000000000000000」である.
例
6:
逆に、ビット列で表されたfloat
型の浮動小数点数を、10進表記にする ことを考える.例えば「1|1000 0001|010. . . 0」の符号は −,
指数は129
であるか1上限が
128
でないのは、バイアアス127
を足した値128 + 127 = 255 = (1111 1111)
2が、別の特定の状況を表すために予約されているからである:仮数部のすべての
bit
が0
のとき、無 限大.そうでない時NaN(not a number)とされている.
また、下限が
−127
でないのは、バイアス127
を足した値−127 + 127 = 0 = (0000 0000)
2が、別の状況を表すために予約されているからである.仮数部のすべての
bit
が0
の時、浮動 小数点数表示された0
を表し、そうでない時非正規化数を表す.2上限、下限の値については、float型の場合同様に、特定の状況を表すために予約されて いる場合を除外している.
ら、バイアスが
127
であることから129 − 127 = 2,
仮数部は2
−2= 0.25
である ことが読みとれる.よって、上の値は、(−1)
1× 2
2× (1 + 0 × 2
−1+ 1 × 2
−2+ 0 × 2
−3+ . . . 0 × 2
23) = −5.0
問
2: float
型のビット列「0|1111 1101|10110. . . 0」を 10
進表記にせよ.2 浮動小数点数の加算
再び
10
進の場合を例にとって、浮動小数点数同士の加算について考える.仮 数には4
桁、指数には2
桁(ともに10
進で)しか保存できないものとする.例
7:
9.999 × 10
1+ 1.610 × 10
−1=?.
まず、指数を調節することで、両方の小数点の位置を合わせる.
1.610 × 10
−1= 0.01610 × 10
1∼ 0.016 × 10
1仮数部に
4
桁しか保持できないので、最後のようになる.ついで、仮数部の和を計算する:
9.999 + 0.016 = 10.015.
よって、全体の値は、10.015
× 10
1である.更に、浮動小数点数表示を正規化(小数点の左が
1
桁になるよう調整)すると、10.015 × 10
1= 1.0015 × 10
2.
しかし、仮数部は
4
桁しか保持できないので、最後の桁の5
を丸めなければな らない.ここでは、四捨五入をとることにする(丸めの方法はいろいろある).したがって、
10.015 × 10
1= 1.0015 × 10
2∼ 1.002 × 10
2.
として最終結果1.002 × 10
2を得る.計算の各過程で、桁溢れが発生する可能性がある.例えば、
•
指数を調整して仮数部の小数点の位置を合わせる際に、指数が2
桁に収ま らなくなる•
丸めを行なうと、浮動小数点表示が正規型(小数点の左に1
桁しかない状 態)ではなくなることがある.例えば、仮数部が9.999
のとき、1/10,000
の桁で繰り上げると、10.000となる.これを再び正規化すると、指数が1
増えるが、すでに指数が99
だった場合、1加えると100
になってしまい、指数に
2
桁しか保持できないという状況に反する.つまり、丸めによる桁 溢れの可能性もある例
8: 10
進の0.5
と−0.4375
の加算を、それぞれ2
進の浮動小数点数表示に直し てから行なう.まず、
0.5 = 2
−1= (1.000)
2× 2
−1−0.4375 = −7/16 = −7 × 2
−4= −(0.0111)
2= −(1.110)
2× 2
−2.
指数が小さな方(−1.110× 2
−2)の仮数を右にシフトして、大きい方と指数 が合うようにする:−(1.110)
2× 2
−2= −(0.111)
2× 2
−1.
仮数部の和を計算:(1.000)
2+ (−0.111)
2= (0.001)
2.
和を正規化する:(0.001)
2× 2
−1= (1.000)
2× 2
−4.
指数の
−4
は、−126と127
の間にあるので、桁溢れはない.(バイアス127
を足 すと、指数は−4 + 127 = 3
である).また、仮数部が
4bit
に収まっているので丸めは必要ない.この値を10
進に直 すと、(1.000)
2× 2
−4= (0.0001000)
2= (0.0001)
2= 2
−4= 1/16 = 0.0625.
10
進で計算した結果と等しい.さらに、浮動小数点数の乗除算、丸め誤差を低減する工夫(ガード桁、丸め 桁)についても考えられるが、この授業ではここまでとする.より詳しくは、任 意の数値解析の教科書を参考のこと.この文書は、パターソン・ヘネシー
[P-H]
の
4
章を参考にした.問
3:
1. double
型の浮動小数点数で表せる、最小の正の値a
を10
進表記で求めよ.2. 1/n! < a
となる自然数n
を求めよ.参考文献
[P-H]
パターソン&ヘネシー著、コンピュータの構成と設計、第2
版、日経BP
社(ISBN 408333-8056-X).