浮動小数点について調べてみた
IT技術
はじめに
こんにちは!
今回は結構ややこしい浮動小数点数について書こうと思います。
普通に計算すると以下のようになります。
0.1 + 0.2 = 0.3
一方でだいたいのプログラミング言語で以下の計算をすると
0.1 + 0.2 => 0.30000000000000004
のように表示されます。
今回はこのなぜ?についてなるべくわかりやすく説明したいと思います。少しでも理解が深まれば幸いです。
コンピュータではどのように計算するか
ご存知のようにコンピュータはデータを2進数で扱います。
それはコンピュータの特性として演算は論理演算に回帰するということが理由になります(深入りしません)。そのために2進数で表現されます。
小数の計算
ここで、一旦分数での計算を考えてみます。
ここに「縛り」を加え、分数は使用できない、小数点以下4桁で切り捨て、という条件を加えます。
すると以下のようになります。
このような縛りがコンピュータでも発生します(データを有限ビットで表現しなくてはならない)。
2進数小数の計算
小数でない場合
2進数にするために係数をひろいます。
少数の場合も同様に以下のように分解します。
2進数にするために係数をひろいます。
しかし、2進数の場合は以下のようになります。
2進数表現 | 10進数分数 | 10進数表現 | |
0.1 | 0.5 | ||
0.01 | 0.25 | ||
0.001 | 0.125 | ||
0.0001 | 0.0625 | ||
0.00001 | 0.03125 | ||
0.000001 | 0.015265 | ||
0.0000001 | 0.0078125 | ||
0.00000001 | 0.00390625 |
ここでを2進数で表現すると循環小数となります。(変換の計算式は調べるとすぐにヒットします)
同様にを2進数で表現すると循環小数となります。
上記の和は以下のような循環小数となります。
コンピュータは有限ビットでデータを保持するので、誤差が発生し、最初の解になるのでした。
0.1 + 0.2 => 0.30000000000000004
浮動小数点とは
上記のように「コンピュータは2進数で演算を行う」「データは有限のビットで扱わなければならない」「2進数の小数は循環小数で多くが表現される」という制約があります。そこで用いられるのが浮動小数点数で表現する形式です。
浮動小数点数はコンピュータで小数を表現するためにルール(IEEEなどの団体)を策定して利用されてます。
一般的に用いられる倍精度浮動小数点数の内部構造は以下のようになります。
その名の通り「符号部」「指数部」「仮数部」で小数を表現します(符号部は簡単なので省く)。
この際に「指数部」、「仮数部」ではそれぞれルールがあり、ルールに基づいて正規化を行います。
例えばは2進数で以下のように表現できます。
これを「仮数」はの条件にすることで、以下の1通りになります。
1の部分は暗黙の「1」として格納されず、仮数部には小数部分のみが格納されます。
したがって、仮数部に格納されるビット(52ビット)は以下となります。
0001000000000000000000000000000000000000000000000000
また「指数部」は11ビット、またバイアスは1023を用いるルールを適用します。
バイアス(オフセット)は非負で表現するために加えます。ですので指数の表現はからまで表現できます。
例えば指数部を、今回正規化したい指数部分をとすると、
したがって、指数部に格納されるビット(11ビット)は以下となります。
1111111100
まとめ
今回は浮動小数点についてふれてみました。
結構データ構造が複雑ですよね。
また、上記のような制約があるので、コンピュータの計算では「丸め誤差」「情報落ち」「桁落ち」などが発生します。
ぜひ深く学ぶきっかけにしてみてください。
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
ライトコードに転職してまだ日は浅いですが、毎日新鮮でワクワクしてます!