【情報I】浮動小数点数とは?IEEE754の仕組みをやさしく解説

【情報I】浮動小数点数とは?IEEE754の仕組みをやさしく解説 分野別講義

「浮動小数点数」と聞くと、それだけで難しそうに感じてしまう人も多いのではないでしょうか。

実はしくみ自体は、それほど複雑ではありません。この記事では、

  • なぜコンピュータは小数をそのまま扱えないのか
  • 浮動小数点数がどうやって数を表しているのか
  • IEEE754という決まりごとの中身(符号部・指数部・仮数部)
  • 実際に自分の手で変換してみる練習

を、一つずつ順番に説明していきます。最後には自分で確かめられる例題も用意していますので、ぜひ手を動かしながら読んでみてください。


なぜ「浮動小数点数」が必要なのか

コンピュータの中では、すべての情報は0と1のビット列で表されています。整数であれば、2進数に変換するだけで表現できました。

では、0.1のような小数はどうでしょうか。

コンピュータが使えるビット数には限りがあります。たとえば32bitと決まっていたら、その32個の0と1だけで、

  • とても大きな数(100000000のような)
  • とても小さな数(0.0000001のような)
  • 細かい小数(3.14159…のような)

を、すべて表現しなければなりません。

もし「整数部分に16bit、小数部分に16bit」のように固定してしまうと(これを固定小数点数といいます)、大きな数も小さな数もうまく表せず、とても不便です。

そこで考え出されたのが、小数点の位置を”浮動”させる(動かせるようにする)という方法です。これが浮動小数点数です。理科の授業で習う「指数表記」を思い出してみてください。

123000=1.23×105123000 = 1.23 \times 10^{5}

0.000123=1.23×10−40.000123 = 1.23 \times 10^{-4}

このように、どんな数も「1桁の数 × 10のべき乗」の形に直せば、桁の大きい数も小さい数も、同じ形式で表現できます。コンピュータはこれを10進数ではなく2進数でおこなっているのです。


2進数の指数表記(正規化)

2進数でも、10進数と同じように指数表記ができます。たとえば2進数の 1011.01 を考えてみましょう。

1011.01(2)=1.01101×231011.01_{(2)} = 1.01101 \times 2^{3}

このように、小数点を先頭の1つだけ残る位置まで動かし、その分だけ指数を調整する作業を正規化といいます。

ポイントは、2進数を正規化すると、必ず先頭が1になるということです。10進数の場合は先頭が1〜9のどれかになり得ますが、2進数には0と1しかないので、0でない数を正規化すれば先頭は必ず1になります。

この「先頭は必ず1」という性質が、後で出てくる仮数部のしくみに直結してきます。


浮動小数点数(IEEE754)という共通ルール

正規化した数を、実際に0と1のビット列としてメモリに保存するときの世界共通のルールが 浮動小数点数(IEEE754) です。ここでは、最もよく使われる「単精度(32bit)」を例に説明します。

32個のビットは、次の3つの部分に分かれています。

部分ビット数役割
符号部(sign)1bit正か負か
指数部(exponent)8bit2の何乗か
仮数部(mantissa / fraction)23bit先頭の1より後ろの数字

符号部(1bit)

正負を表すだけなので、1bitです。

  • 0 → 正の数
  • 1 → 負の数

指数部(8bit) と「バイアス」

指数部は8bitなので、0〜255の整数を表すことができます。しかし実際に表したいのは、2−1262^{-126} のようなマイナスの指数も含みます。

そこで、負の数をそのまま保存するのではなく、127を足した数を保存する、というルールになっています。これをバイアス表現といいます。

保存する値(E)=本当の指数+127\text{保存する値(E)} = \text{本当の指数} + 127

逆に言うと、保存されているビット列を10進数にした値(E)から127を引けば、本当の指数が分かります。

本当の指数=E−127\text{本当の指数} = E – 127

なぜ127かというと、8bitで表せる0〜255のちょうど真ん中あたりに0がくるように選ばれているからです(255ではなく254との兼ね合いなど細かい理由もありますが、「だいたい真ん中」とおぼえておけば十分です)。

仮数部(23bit)と「隠れた1」

先ほど、2進数を正規化すると先頭は必ず1になる、という話をしました。

1.01101×231.01101 \times 2^{3}

この先頭の 1. の部分は、どんな数でも共通して必ず1になるので、わざわざビットを使って保存する必要がありません。IEEE754では、この1を保存せず、小数点より後ろの部分(この例では 01101)だけを23bit分保存します。

これが「隠れたビット」の工夫です。実質24bit分の値を23bitで表せるしくみになっています。


実際に変換してみよう

言葉だけではイメージしづらいので、具体的な数で追ってみましょう。

例1: 10進数 → 浮動小数点数

10進数の 6.5 を 浮動小数点数の32bitで表してみます。

① 2進数に直す

6.5(10)=110.1(2)6.5_{(10)} = 110.1_{(2)}

② 正規化する

110.1(2)=1.101×22110.1_{(2)} = 1.101 \times 2^{2}

③ それぞれの部分を求める

  • 符号部:正の数なので 0
  • 指数部:本当の指数は2なので、2 + 127 = 129 を2進数にして 10000001
  • 仮数部:1.101 の小数点より後ろ 101 を23bitになるよう0で埋めて 10100000000000000000000

④ つなげる

0 10000001 10100000000000000000000

これで完成です。

例2: 浮動小数点数 → 10進数

逆に、次のビット列が表す10進数を求めてみましょう。

1 10000010 01000000000000000000000

① 3つに分ける

  • 符号部:1
  • 指数部:10000010
  • 仮数部:01000000000000000000000

② それぞれ読み取る

  • 符号部が 1 なので、負の数
  • 指数部 10000010 を10進数にすると130。本当の指数は 130 – 127 = 3
  • 仮数部の先頭に隠れた1を戻すと 1.01

③ 組み立てる

−1.01(2)×23=−1010(2)=−10(10) -1.01_{(2)} \times 2^{3} = -1010_{(2)} = -10_{(10)}

答えは -10 です。


自分で解いてみよう(例題)

やり方が分かったところで、実際に手を動かしてみましょう。まずは自分で解いて、答え合わせをしてから、後で紹介するアプリでも確認してみてください。

例題1

10進数の -3.75 を浮動小数点数(32bit)で表しなさい。

解答を見る
  • 3.75(10)=11.11(2)=1.111×213.75_{(10)} = 11.11_{(2)} = 1.111 \times 2^{1}
  • 符号部:負の数なので 1
  • 指数部:本当の指数は1なので、1+127=128 を2進数にして 10000000
  • 仮数部:111 の後ろを0で埋めて 11100000000000000000000

答え:1 10000000 11100000000000000000000

例題2

次のビット列が表す10進数を答えなさい。

0 01111101 01000000000000000000000
解答を見る
  • 符号部が 0 なので正の数
  • 指数部 01111101 = 125。本当の指数は $125-127=-2$
  • 仮数部の先頭に1を戻すと 1.01

1.01(2)×2−2=0.0101(2)=0.3125(10)1.01_{(2)} \times 2^{-2} = 0.0101_{(2)} = 0.3125_{(10)}

答え:0.3125


アプリで確かめよう

手計算での変換に慣れてきたら、自分で作った答えが合っているか、アプリで確かめてみましょう。

数値を入力すればビット列がその場で表示され、逆にビットをクリックして数値がどう変わるかを確認することもできます。「なぜこの計算になるのか」の解説も、各部分に用意してあります。

▶ アプリの使い方はこちらの記事で詳しく紹介しています。
浮動小数点数を可視化できる無料アプリを公開【使い方つき】


注意しておきたい特殊なケース

最後に、浮動小数点数には計算では出てこない少し特殊なビットパターンがあることにも触れておきます。入試で直接問われることは少ないですが、知っておくと安心です。

  • 指数部がすべて0、仮数部もすべて0 → これは「0」を表します。符号部によって +0 と -0 があるのも面白い特徴です。
  • 指数部がすべて1、仮数部がすべて0 → これは「無限大(∞)」を表します。
  • 指数部がすべて1、仮数部が0でない → これは「NaN(Not a Number、非数)」と呼ばれ、「0÷0」のような、計算として成立しない結果を表すために使われます。エラーが起きたときにこのパターンが出てくることがある、と覚えておくとよいでしょう。

これらは今回のアプリでもビットを操作すると実際に作り出せるので、興味があれば触ってみてください。


まとめ

  • コンピュータは指数表記(正規化)を使って、大きい数も小さい数も同じ形式で表している
  • 浮動小数点数は「符号1bit・指数8bit・仮数23bit」の32bitで構成される
  • 指数部は127を足した「バイアス表現」で保存される
  • 仮数部は「先頭の1」を省略して保存する

仕組みが分かれば、あとは手順どおりに変換するだけです。ぜひ何度か練習して、体で覚えてましょう!

コメント

タイトルとURLをコピーしました