新人教育用資料です

概要

  • 浮動小数点(FP[Floating Point]) 数値を指数形式で表現する方式。

指数形式とは、例えば「12345」を「1.2345×10の4乗(1.2345E4)」「0.012345」を「1.2345×10の-2乗(1.2345E-2)」というように表す形式のことである。「整数部○桁/小数部△桁」というように、あらかじめ整数部と小数点以下の有効桁数を固定して表現する「固定小数点」に対し、小数点が有効桁数の間で浮動することからこう呼ばれており、少ないビット数で小さな値や大きな値を効率よく扱えるため、コンピュータの実数演算で広く用いられている。
「1.2345×10の4乗」の「1.2345」を「仮数部」、「4」を「指数部」、「10」を「基数」という。

ビットレイアウト

下図は単精度(float)の場合のレイアウト例。
浮動小数点形式の標準規格である「IEEE 754」の単精度浮動小数点数では、仮数部(Mantissa)に23bit、指数部(Exponent)に8bit(基数は2)、符号に1bitの計32bitで、1.40129846E-45〜3.40282347E38(正の値)の値を表すことができる。ちなみにビット数を2倍の64ビット(仮数部52、指数部11ビット)にしたものが倍精度浮動小数点数である。

#ref(): File not found: "float1.jpg" at page "浮動小数点"

  • 指数部にはbiasとして127を足す。よって指数が0であれば127を足して指数部ビットは01111111(7Fh)となる。
  • Mantissa(仮数部)は、数を2進化してノーマライズ(後述)すると整数部は必ず1になる*1ので省略したもの。例えば10進の3を2進表現すると11だが、これをノーマライズすると「1.1 (x 2の1乗)」になる。この場合のMantissaは小数点以下の部分である1がそれにあたる。同様に、10進の7のMantissaは11となる。

仮数のノーマライズ

ノーマライズ(正規化)とは、桁数が一番上のものだけが整数部になるように小数点の位置を調整することを意味する。 仮数+指数という表現の場合、指数の取り方で何通りもの書き方ができてしまうため、それを一つに統一するため。

10進表現2進表現2進で仮数+指数で表現
31111 x 2^0, 1.1 x 2^1, 0.11 x 2^2, …

10進の3を2進で仮数+指数の形式で書くときには 1.1 x 2^1 (1.1x2の1乗)と書くように決めておく、ということ。

表現したい数(10進)符号指数部(2進)仮数部(2進)全体(16進)
0.500111 111003f 00 00 00
100111 111103f 80 00 00
201000 0000040 00 00 00
301000 0000140 40 00 00
401000 0001040 80 00 00
501000 00010140 A0 00 00
601000 0001140 C0 00 00
701000 00011140 E0 00 00

C#で浮動小数点のメモリイメージをファイル出力してみる

こんな感じになる。

using System;
using System.IO;

class Class1
{
	[STAThread]
	static void Main(string[] args)
	{
		float f = 4f;

		FileStream fs = new FileStream("test.dmp", FileMode.Create);
		BinaryWriter w = new BinaryWriter(fs);
		w.Write(f);
		w.Close();
		fs.Close();
	}
}

出力したファイルのバイナリダンプ

#ref(): File not found: "floatdmp.png" at page "浮動小数点"

IntelアーキテクチャのCPUはリトルエンディアンなのでメモリ上ではバイトオーダーが逆転する点に注意。

精度と誤差について

指数であるために、大小幅広い値をとれるが、精度はあくまで仮数部のビット数止まりであり、その性質上、演算には丸め誤差がつきものとなる。また、10進数ではないために、10進の有限小数でも正確に表現できない場合もある(例えば0.1)。
これは例えば以下のようなプログラムを書いて見ると実感できる。

using System;

class Class1
{
	[STAThread]
	static void Main(string[] args)
	{
		float f = 0.1f;
		float f2 = 0;

		for(int i = 0; i < 10000; i++ ) {
			f2 += f;									 
		}

		Console.WriteLine(f2);
		Console.ReadLine();
	}
}
実行結果:
999.9029

参考リンク

Tutorial: Floating-Point Binary
http://www.nuvisionmiami.com/books/asm/workbook/floating_tut.htm

IEEE Standard 754 Floating Point Numbers
http://research.microsoft.com/~hollasch/cgindex/coding/ieeefloat.html


*1 もちろん0は除く

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2012-08-05 (日) 19:32:40 (3178d)