【浮動小数点数】をわかりやすく説明

Contents

浮動小数点数とは

小数の表現方法の一つ。
対義語は「固定小数点数」。

一般的に2進数を扱うコンピューターで利用されている。

小数点の位置を変えて表現するため”浮動(動く)”の小数点と言われる。
固定小数点数は小数点の位置が固定されて表現されている。

浮動小数点数の例

2進数の 11000000 を浮動小数点数で表すと

1.1 × 27
0.11 × 28
0.011 × 29
0.0011 × 210

となる。

なぜ浮動小数点数が使われるのか?
(浮動小数点数のメリット)

理由は2つ

1.非常に大きな数や小さな数を表現しやすいから。

2.2進数では小数点以下の数値を表すのが不得意だから。

例)
10進数の 0.1 を2進数で表すと
0.000110011001100110011001・・・・
となる。

10進数では単純な小数点数でも桁数が多くなって分かりにくくなる。

それを分かりやすく表現する方法が浮動小数点数形式。

例)
0.00011 → 101 × 2-8

浮動小数点数の構造

浮動小数点数には各箇所に名称がついている。
※重要ではないが、便宜上知っておいた方が良い。

以下の浮動小数点数の各名称は次の通り。

0.11 × 28

0.11 ⇒ 仮数
2 ⇒ 基数
8 ⇒ 指数

 

コンピューターでは仮数、指数を別々に記憶する。
※基数は2進数なので固定。

表現形式のきまり

浮動小数点数は小数点位置が浮動するため、無限の表現形式ができてしまう。

表現形式が統一されていないと計算や情報のやり取りが不便。

そこで、コンピューターで使う浮動小数点数の表現形式は一般的にIEEE754標準で決められた形式を使っている。
※IEEEとは米国電気電子技術協会のこと。

IEEE754の表現形式

IEEE754標準は32ビットの単精度浮動小数点数(単精度とは32ビットのこと。つまり32桁)を次のように表現する。

(-1)s×(2E-127)×(1.M)

各S、E、Mはコンピューターに記憶する値で次のように定義されている。

|S| E |  M  |

S(1ビット)
仮数部の符号(+or-)。0=正、1=負。

E(8ビット)
指数部。IEEE754では指数のバイアス(後述)が127指定されているので、実際の指数から127を足したものとなる。更にそれを2進数で表示する。
例)
2の場合 2+127で129 これを2進数にしてE=10000001となる。

M(23ビット)
仮数部。IEEE754では正規化(後述)するために1の位を0にする。
※1は固定なのでデータとして記憶する必要がないため。
例)
1.011・・・→ 0.011・・・

IEEE754における浮動小数点数の表記例

10進数5.75をIEEE754の浮動小数点数(単精度浮動小数点数)で表してみます。

5.75

→2進数
101.1100

→浮動小数点数(+桁合わせ)
1.0111×22

→IEEE754の形式に合わせる
S は+なので 0
E は2+127で 129 更に2進数に直して 100000001
M は1を0にして  0011100000000000000000

→これを全てくっつけるとIEEE754の単精度浮動小数点数形式(32ビット:32桁)となる。
01000000010011100000000000000000

IEEE754におけるバイアスとは

バイアスはIEEE754の指数部(E)に指定されている数値です。

このバイアスは指数をマイナスにしないようにするための工夫。

実際の指数にはマイナスがあるが、仮数部にもマイナスがある可能性があるので両方の符号を考慮するとややこしくなるし、余計なビットを消費することとなる。

そこで、指数にゲタを履かせてマイナスが出ないようにする。
※8ビット表記なので指数は最小でも127を足せばマイナスにならない。

バイアスが127である必要はないが、2進数8ビットの10進数の範囲は0~255なので中間辺りの127が計算する上で都合が良いとされた。

浮動小数点数の正規化とは?

2進数は10進数と誤差がでる。

10進数を2進数に変換すると小数点以下が多くなる傾向があり、IEEE754の単精度浮動小数点数は32桁までしか考慮せず、それ以降は切り捨てられるため誤差がでる。

この誤差を少なくするための工夫が「浮動小数点数の正規化」と呼ばれる。

IEEE754では仮数における小数点の左側が必ず1になる(1.M)ように正規化されることがルールとして決まっている。

例)
0.1101 → 1.101×2-1

浮動小数点数の欠点・注意点

誤差

コンピューターでは浮動小数点数は基本的に桁数が制限されているため演算上誤差が生じやすくなる。

これは2進数と10進数の変換によって循環小数が発生することが主な要因となるが、最大の原因は桁数を固定することにある。

簡単な例で言うと、

円周率は3.14という3桁で表されるが、実際の円周率は3.14159265358979323846・・・であり、3.14という数値は実際の円周率とは誤差がある。

というようなことが10進数と2進数の間では頻繁に発生し、更にこの誤差を持った数値が計算に使われることで、更に誤差が発生するわけです。

浮動小数点数における誤差には以下のような種類がある。

仮数部で発生する誤差

丸め誤差

仮数部が循環小数となった場合に特定の桁数で四捨五入や切捨てなどの処理を行うことにより発生する誤差。

10進数を2進数に変換する際、循環小数が発生することがある。

浮動小数点数は仮数(の桁)が有限になるので、その桁で四捨五入や切上げ切捨てなどの処理が行われ、誤差が生じる。その誤差を丸め誤差と言う。

例)
0.2(10進数)→2進数に変換→ 0.00110011001100110011001100110011・・・

循環小数となる

仮数部を32ビットで表すと少数第24以降は切捨てとなる。
※この処理を”丸められる”と言う。

0.0011001100110011001100

この数値を10進数に戻しても0.2にはならない。
0.19999980926513671875(10進数)

桁落ち

桁落ちとは桁数が決まっている浮動小数点数において、絶対値がほぼ等しい数値を減算した時に、実際の数値と比べて著しく桁数が減る誤差のことを言います。
※桁が落ちるのは基本的に少数以下の部分です。

絶対値がほぼ等しい数値同士を引くとその差異は非常に小さな値となる。

浮動小数点数では桁数が決まっているので、その非常に小さい値は切捨てられる場合が多い。

更に正規化すると、本来その非常に小さい値は大きな値になる可能性があるが、切捨てられているので0となり、実際の数値より小数点以下の桁数が大きく減ってしまいます。

これを桁落ちの誤差と言います。

例)
まず次のような絶対値のほぼ等しい数値があるとします。
A=1.1111111123334455667788
B=1.111111111111111111111122

A-Bを行います。

A-B=0.000000012223344556666

これを正規化します。

1.2223344556666×107  →(あ)

この引き算を、有効桁数を10桁の浮動小数点で計算すると以下になります。

a=1.111111123
b=1.111111111

a-bを行います。

a-b=0.000000012

これを正規化します。

=1.200000000×107 →(い)

前述の(あ)を有効桁数10桁にします。

1.222334455×107 →(う)

(い)は(う)と比べて桁数が減少し、ほぼ等しい数値なのにも関わらず大きな誤差が出ていることが分かります。

(う)1.222334455×107
(い)1.200000000×107

情報落ち

絶対値の差が非常に大きい2つの数値の加減算を行った時に小さい値が無視されてしまうことを情報落ちの誤差と言います。

これは桁数の決まっている浮動小数点数の計算において発生する現象です。

浮動小数点数の加減算は指数部を大きい方に揃えてから仮数部同士の計算をするため、数値の差が大きいと小さい値は指数を大きくするために仮数部が0になってしまうからです。

例)
まず次のような絶対値の非常に大きな数値があるとします。
A=1100000000000
B=0.11

A+Bを行います。

A+B=1100000000000.11 →(あ)

両者を10桁の浮動小数点数に変換します。
a=1100000000000 → 1.100000000×1012
b=0.11 → 1.100000000×10-1

A+Bを行います。
bの指数をaに合わせるために12にします。

b=0.000000000×1012

仮数部分が0となってしまい情報が落ちてしまう誤差が生まれる。
よって、a-bを計算すると、

a-b = 1.100000000×1012  - 0.000000000×1012   = 1.100000000×1012

となり、aの値と同じになる。つまりbの情報は落ちてしまう。

打切り誤差

無限小数などの値に対し、ある程度の時点で処理を打ち切ることで発生する誤差。

丸め誤差との違い

丸め誤差:
10進数から2進数に変換する際などに特定の桁数で四捨五入や切捨てなどを行うことで生じる誤差。

打切り誤差:
円周率など無限小数が続く計算を途中で止めることで生じる誤差。

誤差を理解することが何故重要なのか?

コンピューターは浮動小数点数を使う。

つまり、コンピューターの演算は誤差が発生しやすい。

よって、その誤差が発生しにくいように対処する必要がある。(例えば、足し算・掛け算を先に計算したり、大きな数字の計算を先にしたりする)

そのために誤差の性質を理解する必要がある。

指数部で発生する誤差

指数部で発生する誤差には主に以下の二つがあります。ただし、両者とも指数部特有の誤差というわけではなく、指数部で発生しやすい誤差と考えて良いです。

オーバーフロー

本来は処理できる値よりも大きな値が発生した時に起こる誤差(というかエラー)です。

簡単な例)
2桁しか表現できない場合、40+60を行うと答えの100が処理できずオーバーフローとなり、00となったりする。

IEEE754の場合、指数が2127を超えるとオーバーフローとなります。

アンダーフロー

本来は処理できる値よりも小さな値が発生した時に起こる誤差(というかエラー)です。

簡単な例)
2桁しか表現できない場合、ー40ー60を行うと答えのー100が処理できずアンダーフローとなり、00となったりする。

IEEE754の場合、指数が2-126よりも小さいとオーバーフローとなります。

誤差を少なくする方法

誤差を少なくするには、次のような方法がある。

用語解説

丸め誤差(まるめごさ)

浮動小数点数において、仮数部が循環小数となった場合に特定の桁数で四捨五入や切捨てなどの処理を行うことにより、実際の数値との誤差が発生する。

10進数を2進数に変換した際などによく発生する。

絶対値(ぜったいち)

数の大きさのこと。つまり+ーは関係ない。-5の絶対値は5。