- 追加された行はこの色です。
- 削除された行はこの色です。
- 浮動小数点 へ行く。
新人教育用資料です
#contents
*概要 [#j25afd1c]
-浮動小数点(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」を「''基数''」という。
*ビットレイアウト [#td90016b]
下図は単精度(float)の場合のレイアウト例。~
浮動小数点形式の標準規格である「IEEE 754」の単精度浮動小数点数では、仮数部(Mantissa)に23bit、指数部(Exponent)に8bit(基数は2)、符号に1bitの計32bitで、1.40129846E-45〜3.40282347E38(正の値)の値を表すことができる。ちなみにビット数を2倍の64ビット(仮数部52、指数部11ビット)にしたものが倍精度浮動小数点数である。
-指数部にはbiasとして127を足す。よって指数が0であれば127を足して指数部ビットは01111111(7Fh)となる。
-Mantissa(仮数部)は、数を2進化してノーマライズ(後述)すると整数部は必ず1になる((もちろん0は除く))ので省略したもの。例えば10進の3を2進表現すると11だが、これをノーマライズすると「1.1 (x 2の1乗)」になる。この場合のMantissaは小数点以下の部分である1がそれにあたる。同様に、10進の7のMantissaは11となる。
**仮数のノーマライズ [#c96b940a]
ノーマライズ(正規化)とは、桁数が一番上のものだけが整数部になるように小数点の位置を調整することを意味する。
仮数+指数という表現の場合、指数の取り方で何通りもの書き方ができてしまうため、それを一つに統一するため。
|10進表現|2進表現|2進で仮数+指数で表現|h
|3|11|11 x 2^0, 1.1 x 2^1, 0.11 x 2^2, …|
10進の3を2進で仮数+指数の形式で書くときには ''1.1 x 2^1'' (1.1x2の1乗)と書くように決めておく、ということ。
*例 [#q47cb0b0]
|表現したい数(10進)|符号|指数部(2進)|仮数部(2進)|全体(16進)|h
|0.5|0|0111 1110|0|3f 00 00 00|
|1|0|0111 1111|0|3f 80 00 00|
|2|0|1000 0000|0|40 00 00 00|
|3|0|1000 0000|1|40 40 00 00|
|4|0|1000 0001|0|40 80 00 00|
|5|0|1000 0001|01|40 A0 00 00|
|6|0|1000 0001|1|40 C0 00 00|
|7|0|1000 0001|11|40 E0 00 00|
*C#で浮動小数点のメモリイメージをファイル出力してみる [#i3f40fbb]
こんな感じになる。
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();
}
}
IntelアーキテクチャのCPUはリトルエンディアンなのでメモリ上ではバイトオーダーが逆転する点に注意。
*精度と誤差について [#c7f328f1]
指数であるために、大小幅広い値をとれるが、精度はあくまで仮数部のビット数止まりであり、その性質上、演算には丸め誤差がつきものとなる。また、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
*参考リンク [#v4021828]
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