浮動小数点の基礎知識

2014-03-10 00:00:00 +0000

浮動小数点の基礎知識について説明します。

今回は浮動小数点の基礎知識について説明します。 浮動小数についてきちんと理解している人は意外と少ないのではないでしょうか。

浮動小数点は多くのプログラミングで利用されている実数の表現方式です。 C言語などの言語で使われるdoubleやfloatは浮動小数点型です。 対してintやlongなどは整数型です。

浮動小数点の仕様はIEEE 754: Standard for Binary Floating-Point Arithmeticとして策定されていますが、WikipediaのIEEE 754がわかりやすいと思います。 ざっくり説明すると、なじみのあるdoubleとfloatはそれぞれ倍精度浮動小数点、単精度浮動小数点とよばれ、それぞれ64bitと32bitで表現され、そのbit表現は符号部、指数部、小数部によって構成されます。 倍精度と単精度のそれぞれの部に割り当てられるbit数は以下のようになります。

符号部指数部小数部
倍精度1bit11bit52bit
単精度1bit8bit23bit

単精度の浮動小数点は次のように求めることができます。

\displaystyle value = (-1)^{sign} \sum^{23}_{i=1} \left( 1 + b_i 2^{-i} \right) \times 2^{e-127}

同様に倍精度の場合には次のようになります。

\displaystyle value = (-1)^{sign} \sum^{52}_{i=1} \left( 1 + b_i 2^{-i} \right) \times 2^{e-1023}

では、実際にバイナリ表現から浮動小数点を生成してみましょう。 単精度の1.0は上記の式で

sign=0, \forall b_i=0, e=127

のときです。bit列にすると、

00111111 1000000000 00000000 00000000

です。16進数表現にすると

3f 80 00 00

ですね。これを次のようにリトルエンディアンに注意して、char型の配列に格納し、その配列の先頭アドレスをfloatのポインタとして解釈することで、バイト列をfloatとして解釈します。

#include <stdio.h>

int main()
{
  char a [] = { 0x00, 0x00, 0x80, 0x3f };
  float f = *((float*)a);
  printf ("%f\n", f);
  return 0;
}

そしてコンパイルして実行します。

$ gcc test.c
$ ./a.out
1.000000

実際に1.0が表示されました。 同様に倍精度の1.0の場合についても確認しましょう。

sign=0, \forall b_i=0, e=1023

となるので、bit列は

00111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000

となり、16進数表現では

3f f0 00 00 00 00 00 00

となります。同様にリトルエンディアンに注意してバイト列をdouble型として認識させます。

#include <stdio.h>

int main()
{
  char a [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f };
  double d = *((double*)a);
  printf ("%f\n", d);
  return 0;
}

コンパイルして実行します。

$ gcc test.c
$ ./a.out
1.000000

1.0が表示されることを確認できます。

#include <stdio.h>

int main()
{
  char a [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f };
  double d = *((double*)a);
  printf ("%f\n", d);
  return 0;
}

コンパイルして実行します。

$ gcc test.c
$ ./a.out
inf

infが表示されることを確認できます。

#include <stdio.h>

int main()
{
  char a [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff };
  double d = *((double*)a);
  printf ("%f\n", d);
  return 0;
}

コンパイルして実行します。

$ gcc test.c
$ ./a.out
-inf

-infが表示されることを確認できます。

関連する記事

将棋DB2
プロ棋士からコンピューター将棋の棋譜まで観られる将棋の棋譜サービス
将棋DB iOS
将棋DB2のiOSアプリ
将棋DB Android
将棋DB2のAndroidアプリ
碁DB
プロ棋士からコンピューター囲碁の棋譜まで観られる囲碁の棋譜サービス