LoginSignup
1
2

More than 3 years have passed since last update.

Float5で浮動小数点数を振り返る

Posted at

浮動小数点数の特徴を振り返ってみます。

ビット列

 コンピューターの最終単位はビット。0か1です。しかし、0か1だけでは表現の幅がないので、複数の0か1を組み合わせることで数字など表します。ここでは、5ビットの数字を考えてみます。
 ※どうして5ビットにしたかというと、全部のビットの組み合わせを表示できるというだけで、実用的には全く意味がありません。なお、本記事中、数字の後に2とあるのは、2進数という意味です。

UInt5

 5ビットで考えられる基本的な数字と云えば、符号なし整数「UInt5」です。

ビット列 数字 ビット列 数字 ビット列 数字 ビット列 数字
00000 0 01000 8 10000 16 11000 24
00001 1 01001 9 10001 17 11001 25
00010 2 01010 10 10010 18 11010 26
00011 3 01011 11 10011 19 11011 27
00100 4 01100 12 10100 20 11100 28
00101 5 01101 13 10101 21 11101 29
00110 6 01110 14 10110 22 11110 30
00111 7 01111 15 10111 23 11111 31

 これは、000002を0と定義し、1増やすごとに「最下位ビットが0なら1にする。最下位ビットが1なら0にして、一つ上のビットを確認する。そのビットが0なら1にする。1なら0にしてもう一つ上のビットを・・・」の繰り返しです。最終的に111112になり、さらに1増やすと000002に戻ります。
 現在一般的なパソコン用CPUは、このような手順でUInt8, UInt16,...を定義しているかと思います。

Int5

 符号なし整数よりもよく使われるのが符号あり整数「Int5」です。

Int5(2の補数表現)

ビット列 10進数 ビット列 10進数 ビット列 10進数 ビット列 10進数
00000 0 01000 8 10000 -16 11000 - 8
00001 1 01001 9 10001 -15 11001 - 7
00010 2 01010 10 10010 -14 11010 - 6
00011 3 01011 11 10011 -13 11011 - 5
00100 4 01100 12 10100 -12 11100 - 4
00101 5 01101 13 10101 -11 11101 - 3
00110 6 01110 14 10110 -10 11110 - 2
00111 7 01111 15 10111 - 9 11111 - 1

 「2の補数表現」と呼ばれる定義です。000002から011112まではUInt5と同じ、011112と100002の間を除けば1ずつ増えていくところもUInt5と同じです。
 「100002は-1610ではなく+1610と定義してもよいのでは?」とも思いますが、-1610と定義しておくと「最上位ビットが1なら負の数である」と統一できるので、比較演算などの時に便利です。

Int5(符号+絶対値表現)

 ほかにも

ビット列 10進数 ビット列 10進数 ビット列 10進数 ビット列 10進数
00000 0 01000 8 10000 0 11000 - 8
00001 1 01001 9 10001 - 1 11001 - 9
00010 2 01010 10 10010 - 2 11010 -10
00011 3 01011 11 10011 - 3 11011 -11
00100 4 01100 12 10100 - 4 11100 -12
00101 5 01101 13 10101 - 5 11101 -13
00110 6 01110 14 10110 - 6 11110 -14
00111 7 01111 15 10111 - 7 11111 -15

 という定義も考えられます。最上位ビットで符号をあらわし、それ以外のビットで絶対値を表しています。
 人が見るとわかりやすいのですが、コンピューターが計算するには少々やっかいなところがあります。

 2の補数表現で 510+(-310)=210 をあらわすと、001012 + 111012 = 000102 になります。
 符号+絶対値表現で 510+(-310)=210 をあらわすと、 001012 + 100112 = 000102 になります。
ここで、同じビット列のUInt5の足し算は、
001012 + 111012 = 000102 (左辺が2の補数表現の510+(-310)と同じビット列)
001012 + 100112 = 110002 (左辺が符号+絶対値表現の510+(-310)と同じビット列)
となり、2の補数表現の場合とUInt5の場合の右辺が同じになります。つまり、2の補数表現を使えば、UInt5とInt5で同じ加算処理を使えるのでCPU設計が簡単になるかと思います。

Int5(バイアス表現)

ビット列 10進数 ビット列 10進数 ビット列 10進数 ビット列 10進数
00000 -15 01000 - 7 10000 1 11000 9
00001 -14 01001 - 6 10001 2 11001 10
00010 -13 01010 - 5 10010 3 11010 11
00011 -12 01011 - 4 10011 4 11011 12
00100 -11 01100 - 3 10100 5 11100 13
00101 -10 01101 - 2 10101 6 11101 14
00110 - 9 01110 - 1 10110 7 11110 15
00111 - 8 01111 0 10111 8 11111 16

 という定義もできます。UInt5から15を引いた(バイアスを加えた)、という定義です。000002から111112まで1ずつ増加するので大小の比較が簡単になりますが、符号+絶対値表現と同様に、UInt5とは別の加算処理を行う必要があります。

Float5

 IEEE754 にある binary16を参考に、Float5を定義してみます。
 表現したい数字cを、c = ± a × 2b という指数表現にし、Float5の最上位ビットは符号、続く2ビットを指数部b、下位2ビットを仮数部aに割り当てます。
 符号は、正を0、負を1で表します。これは、2の補数表現や符号+絶対値表現と同じです。
 指数部bは、以下のように割り当てます。

ビット列 10進数
00 -1
01 0
10 1
11 2

 これは、Int5の最後に紹介したバイアス表現と同じです。
 続いて、仮数部aは、以下のように割り当てます。

ビット列 10進数 2進数 補足
00 1.00 1.00 指数部が00の場合は0.00
01 1.25 1.01
10 1.50 1.10
11 1.75 1.11 指数部が11の場合は無限大

 10進数表現がわかりづらいので、2進数表現もつけました。10進数の場合、指数表現では(整数部1桁.小数部)×10指数部と表現します。2進数の場合も同様に整数部を1桁で表すのですが、1桁に0か1しかありませんので、表現したい値cが0の場合を除けば、整数部は必ず1になります。そこで、整数部を1に固定し、小数点以下2桁にビット列を割り当てます。これで有効桁数を若干増やしています。

さて、以上を踏まえると、Float5は以下のようになります。

ビット列 10進数 ビット列 10進数 ビット列 10進数 ビット列 10進数
00000 +0.00×2-1=0.000 01000 +1.00×21=2.000 10000 -0.00×2-1=-0.000 11000 -1.00×21=-2.000
00001 +1.25×2-1=0.625 01001 +1.25×21=2.500 10001 -1.25×2-1=-0.625 11001 -1.25×21=-2.500
00010 +1.50×2-1=0.750 01010 +1.50×21=3.000 10010 -1.50×2-1=-0.750 11010 -1.50×21=-3.000
00011 +1.75×2-1=0.875 01011 +1.75×21=3.500 10011 -1.75×2-1=-0.875 11011 -1.75×21=-3.500
00100 +1.00×2 0=1.000 01100 +1.00×22=4.000 10100 -1.00×2 0=-1.000 11100 -1.00×22=-4.000
00101 +1.25×2 0=1.250 01101 +1.25×22=5.000 10101 -1.25×2 0=-1.250 11101 -1.25×22=-5.000
00110 +1.50×2 0=1.500 01110 +1.50×22=6.000 10110 -1.50×2 0=-1.500 11110 -1.50×22=-6.000
00111 +1.75×2 0=1.750 01111 +無限大 10111 -1.75×2 0=-1.750 11111 -無限大

 さて、浮動小数点数を扱うときに気をつけなければならないことの一つに、10進数の小数がそのまま表せないと云うことがあります。見てのとおり、0.110刻みの数値を表すことはできません。意外にも、「仮数部2桁の2進数だから、0.2510, 0.5010, 0.7510は表現できる」と思いきや、0.7510しか表現できません。
 そして、もう一つ気をつけないといけないのが、数値の間隔(分解能)です。000012から000112までは各値の間隔が0.2510です。しかし、011002から011102までは間隔が1.0010になります。このように、指数部が大きくなるごとに数値の間隔が広くなってきます(ただし、000002から000012の間だけ広くなっています)。
 

まとめ

 浮動小数点数といえば、「10進数の小数が表せないことがある」点が取り上げられがちですが、「0から離れるほど数値の間隔が広くなる(分解能が落ちる)」ということも気をつける必要がありそうです。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2