倍精度って何よ?

はい、自分でも存在を忘れてましたが、このブログは入門プログラムも扱ってたんですねぇ。
普通に忘れてました…orz
というか、このブログだとプログラムのソース書き辛いんですよねぇ…
某大学の基礎情報処理という授業のTA (Teaching Assistant:教員補助)やってますので、いわば仕事の流れなんですけどね。
 
今回は倍精度でよくされる質問について触れたいと思います。
つまり、float型とdouble型の違いを語っていきたいと思います。
 
C言語には基本的に5つの変数型があります。
その中で小数点付の数(プログラムの教科書では実数と表記してある数)を扱えるのは次の2つです。
まずはfloat型(浮動小数点型)。
もう一つはdouble型(倍精度浮動小数点型)。
どちらの型で宣言された変数も、符号付の浮動小数点数を格納することができます。
では何が違うのか。
float型とdouble型の違いとして、扱える精度があります。
浮動小数の表記法はIEEE754で規定されています。
IEEE754によると、浮動小数は
 
(-1)S × (1 + M) × 2E
 
※S = 符号部、 E = 指数部、 M = 仮数部
で表現することができます。
float型(単精度)とdouble型(倍精度)も同じ式で表すことができます。
ただし、割り当てられているビット数がfloatとdoubleでは異なります。
32bitコンピュータの場合、変数には32bit = 4Byteの領域を取り扱うことができます。
float型も4Byteを取り扱うことができます。
 
□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
 
= 符号部(1bit)、  = 指数部(8bit)、  = 仮数部(23bit)
 
指数部 – 127 が指数の値、仮数部は仮数の小数点以下を表しています。
つまり、仮数は仮数部の先頭に1.をつけたものとなります。
それを式にすると以下の通り。
 
floatの表示値 = (-1)符号部 × 1.仮数部 × 2指数部 – 127
 
上記より、32bitコンピュータの場合の絶対値の範囲は2-126~2128(約10-38~1038)および0ということになります。
また、取り扱える桁数は2進数で24 (23 + 1)桁(10進数だと約6~7桁)となります。
また、float型で表せる実数はfloat.hで次のように定義されています。
 
1.175494 × 10-38 ~ 3.402823 × 1038
 
一方double型は64bit = 8Byteと、float型の2倍割り当てられています。
 
□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
 
= 符号部(1bit)、  = 指数部(11bit)、  = 仮数部(52bit)
 
指数部 – 1023 が指数の値となり、仮数部は仮数の小数点以下を表しています。
floatのときと同じように仮数は仮数部の先頭に1.をつけた値となります。
 
doubleの表示値 = (-1)符号部 × 1.仮数部 × 2指数部 – 1023
 
上記より、32bitコンピュータの場合の絶対値の範囲は2-1022~21024(約10-308~10308)および0ということになります。
また、取り扱える桁数は2進数で53 (52 + 1) 桁(10進数では約15~16桁)になります。
こちらもfloat型と同様にdouble型で表せる実数はfloat.hで次のように定義されています。
 
2.225074 × 10-308 ~ 1.797693 × 10308
 
これを纏めると以下の表になります。

 

単精度

倍精度

符号部(S)

1(bit)

1(bit)

指数部(E)

8(bit)

11(bit)

仮数部(M)

23(bit)

52(bit)

表1 単精度と倍精度の記憶領域の割当
 
以上で、double型とfloat型の違いの説明とします。
少なくともよく出る疑問の、6桁の倍の12桁違うんかいなという理由はお判りいただけたと思います。
10進数で仮数部を表すと、float型の場合は約7桁(実際は6桁)が保証精度、double型の場合は約16桁(実際は15桁)が保証精度なんですね。
倍精度の倍は桁数が倍ではなくて、記憶領域が倍っていう意味で、記憶領域をfloat型の倍にすることで精度の向上を図ったのがdouble型だとご理解いただけたと思います。
 
ちなみに現在のコンピュータではほとんどdouble型を使っています。
その理由として、精度が高いことと計算速度が速いことが挙げられます。
float型と違い、2倍の領域を使うdouble型は2倍のメモリの領域を消費しますが、現時のコンピュータではそんなこと気にならないぐらいメモリの容量があります。
そのことでより高精度な演算を行うことができます。
ただ、速くなるというのは腑に落ちないかと思います。
余計な演算が含まれていない分、単精度のほうが速いような気がする方も当然いらっしゃるでしょう。
そこの説明をしておくと、現在のコンピュータはdouble型のデータを扱うことが前提になっています。
回路もdouble型を行うことを前提で設計されていますし、コンパイラもdouble型を利用することを前提としています。
そのためfloat型で計算を行う際、double型に自動的に変換してから計算を実行し、再びfloat型に変換し直すという無駄が生じ、計算時間が多くなります。
VisualCのコンパイラをコマンドラインで利用したらわかりますが、勝手にfloat型からdouble型に変換しますよという趣旨のメッセージが表示されます。
特に理由がない限りは、実数を扱う場合はdouble型を使っておくことが無難だと思います。
ただし、double型も万能ではなく、所詮は近似値だということを頭に入れておいてください。
コンピュータの記憶領域は無限ではなく、有限です。
科学計算のように、完璧な値ではなくおおよその精度を持ちつつ完璧な値に近似的な値を必要とする場合に、如何に有限な記憶領域の中で絶対値が大きな値を高精度で計算するかを求めた結果が浮動小数点型や倍精度浮動小数点型なわけですから。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中